2007-09-12 03:57:59 +04:00
/*
2002-01-30 09:08:46 +03:00
Unix SMB / CIFS implementation .
1996-05-04 11:50:46 +04:00
Main SMB reply routines
1998-01-22 16:27:43 +03:00
Copyright ( C ) Andrew Tridgell 1992 - 1998
2001-09-16 10:35:35 +04:00
Copyright ( C ) Andrew Bartlett 2001
2007-01-13 02:47:16 +03:00
Copyright ( C ) Jeremy Allison 1992 - 2007.
2007-08-02 22:28:41 +04:00
Copyright ( C ) Volker Lendecke 2007
2001-09-16 10:35:35 +04:00
1996-05-04 11:50:46 +04: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-09 23:25:36 +04:00
the Free Software Foundation ; either version 3 of the License , or
1996-05-04 11:50:46 +04:00
( at your option ) any later version .
2007-09-12 03:57:59 +04:00
1996-05-04 11:50:46 +04: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 .
2007-09-12 03:57:59 +04:00
1996-05-04 11:50:46 +04:00
You should have received a copy of the GNU General Public License
2007-07-10 04:52:41 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
1996-05-04 11:50:46 +04:00
*/
/*
This file handles most of the reply_ calls that the server
makes to handle specific protocols
*/
# include "includes.h"
2018-03-10 17:31:11 +03:00
# include "libsmb/namequery.h"
2011-02-26 01:20:06 +03:00
# include "system/filesys.h"
2010-05-04 12:28:48 +04:00
# include "printing.h"
2020-10-28 14:09:39 +03:00
# include "locking/share_mode_lock.h"
2011-03-22 18:57:01 +03:00
# include "smbd/smbd.h"
2009-01-08 14:03:45 +03:00
# include "smbd/globals.h"
2021-10-26 14:48:28 +03:00
# include "smbd/smbXsrv_open.h"
2010-08-18 18:44:47 +04:00
# include "fake_file.h"
2011-04-13 16:32:16 +04:00
# include "rpc_client/rpc_client.h"
2011-01-15 13:53:11 +03:00
# include "../librpc/gen_ndr/ndr_spoolss_c.h"
2010-05-07 13:03:32 +04:00
# include "rpc_client/cli_spoolss.h"
2010-07-31 02:47:20 +04:00
# include "rpc_client/init_spoolss.h"
2010-07-07 23:24:30 +04:00
# include "rpc_server/rpc_ncacn_np.h"
2010-10-12 08:27:50 +04:00
# include "libcli/security/security.h"
2011-03-23 16:18:59 +03:00
# include "libsmb/nmblib.h"
2011-03-24 15:46:20 +03:00
# include "auth.h"
2011-04-14 02:36:23 +04:00
# include "smbprofile.h"
2011-06-16 17:45:18 +04:00
# include "../lib/tsocket/tsocket.h"
2020-03-12 19:51:53 +03:00
# include "lib/util/tevent_ntstatus.h"
2012-08-03 10:44:39 +04:00
# include "libcli/smb/smb_signing.h"
2015-10-12 16:57:34 +03:00
# include "lib/util/sys_rw_data.h"
2019-06-13 13:58:02 +03:00
# include "librpc/gen_ndr/open_files.h"
2020-02-04 15:58:02 +03:00
# include "libcli/smb/smb2_posix.h"
2020-08-07 21:17:34 +03:00
# include "lib/util/string_wrappers.h"
2021-03-11 20:02:44 +03:00
# include "source3/printing/rap_jobid.h"
2021-11-10 22:18:07 +03:00
# include "source3/lib/substitute.h"
1996-05-04 11:50:46 +04:00
2023-01-10 04:33:14 +03:00
/****************************************************************************
Check if we have a correct fsp pointing to a file . Basic check for open fsp .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
bool check_fsp_open ( connection_struct * conn , struct smb_request * req ,
files_struct * fsp )
{
if ( ( fsp = = NULL ) | | ( conn = = NULL ) ) {
reply_nterror ( req , NT_STATUS_INVALID_HANDLE ) ;
return false ;
}
if ( ( conn ! = fsp - > conn ) | | ( req - > vuid ! = fsp - > vuid ) ) {
reply_nterror ( req , NT_STATUS_INVALID_HANDLE ) ;
return false ;
}
return true ;
}
2023-03-30 16:55:53 +03:00
/****************************************************************************
SMB1 version of smb2_strip_dfs_path ( )
Differs from SMB2 in that all Windows path separator ' \ ' characters
2023-03-31 12:44:00 +03:00
have already been converted to ' / ' by check_path_syntax ( ) .
2023-03-30 16:55:53 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
NTSTATUS smb1_strip_dfs_path ( TALLOC_CTX * mem_ctx ,
uint32_t * _ucf_flags ,
char * * in_path )
{
uint32_t ucf_flags = * _ucf_flags ;
char * path = * in_path ;
char * return_path = NULL ;
if ( ! ( ucf_flags & UCF_DFS_PATHNAME ) ) {
return NT_STATUS_OK ;
}
2023-07-18 12:30:18 +03:00
/* Strip any leading '/' characters - MacOSX client behavior. */
2023-03-30 16:55:53 +03:00
while ( * path = = ' / ' ) {
path + + ;
}
/* We should now be pointing at the server name. Go past it. */
for ( ; ; ) {
if ( * path = = ' \0 ' ) {
/* End of complete path. Exit OK. */
goto done ;
}
if ( * path = = ' / ' ) {
/* End of server name. Go past and break. */
path + + ;
break ;
}
path + + ; /* Continue looking for end of server name or string. */
}
/* We should now be pointing at the share name. Go past it. */
for ( ; ; ) {
if ( * path = = ' \0 ' ) {
/* End of complete path. Exit OK. */
goto done ;
}
if ( * path = = ' / ' ) {
/* End of share name. Go past and break. */
path + + ;
break ;
}
if ( * path = = ' : ' ) {
/* Only invalid character in sharename. */
return NT_STATUS_OBJECT_NAME_INVALID ;
}
path + + ; /* Continue looking for end of share name or string. */
}
done :
/* path now points at the start of the real filename (if any). */
/* Duplicate it first. */
return_path = talloc_strdup ( mem_ctx , path ) ;
if ( return_path = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
/* Now we can free the original (path points to part of this). */
TALLOC_FREE ( * in_path ) ;
* in_path = return_path ;
ucf_flags & = ~ UCF_DFS_PATHNAME ;
* _ucf_flags = ucf_flags ;
return NT_STATUS_OK ;
}
2023-01-10 04:33:14 +03:00
/****************************************************************************
Check if we have a correct fsp pointing to a file .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
bool check_fsp ( connection_struct * conn , struct smb_request * req ,
files_struct * fsp )
{
if ( ! check_fsp_open ( conn , req , fsp ) ) {
return false ;
}
if ( fsp - > fsp_flags . is_directory ) {
reply_nterror ( req , NT_STATUS_INVALID_DEVICE_REQUEST ) ;
return false ;
}
if ( fsp_get_pathref_fd ( fsp ) = = - 1 ) {
reply_nterror ( req , NT_STATUS_ACCESS_DENIED ) ;
return false ;
}
fsp - > num_smb_operations + + ;
return true ;
}
1996-05-04 11:50:46 +04:00
/****************************************************************************
1999-12-13 16:27:58 +03:00
Reply to a tcon .
2006-06-20 06:38:28 +04:00
conn POINTER CAN BE NULL HERE !
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
2008-01-05 02:37:24 +03:00
void reply_tcon ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
2002-08-17 19:27:10 +04:00
const char * service ;
2007-07-13 05:22:09 +04:00
char * service_buf = NULL ;
char * password = NULL ;
char * dev = NULL ;
1998-08-14 21:38:29 +04:00
int pwlen = 0 ;
2001-09-24 03:07:53 +04:00
NTSTATUS nt_status ;
2014-02-26 23:16:26 +04:00
const uint8_t * p ;
const char * p2 ;
2007-09-11 22:31:29 +04:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
2014-06-11 17:12:32 +04:00
struct smbXsrv_connection * xconn = req - > xconn ;
2012-11-01 16:53:27 +04:00
NTTIME now = timeval_to_nttime ( & req - > request_time ) ;
2007-07-13 05:22:09 +04:00
2000-10-06 07:21:49 +04:00
START_PROFILE ( SMBtcon ) ;
1998-08-14 21:38:29 +04:00
2008-11-01 18:24:42 +03:00
if ( req - > buflen < 4 ) {
2007-08-17 05:55:58 +04:00
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBtcon ) ;
return ;
}
2007-08-15 14:29:47 +04:00
2014-02-26 23:16:26 +04:00
p = req - > buf + 1 ;
2008-11-02 03:07:46 +03:00
p + = srvstr_pull_req_talloc ( ctx , req , & service_buf , p , STR_TERMINATE ) ;
p + = 1 ;
pwlen = srvstr_pull_req_talloc ( ctx , req , & password , p , STR_TERMINATE ) ;
p + = pwlen + 1 ;
p + = srvstr_pull_req_talloc ( ctx , req , & dev , p , STR_TERMINATE ) ;
p + = 1 ;
1998-08-14 21:38:29 +04:00
2007-07-13 05:22:09 +04:00
if ( service_buf = = NULL | | password = = NULL | | dev = = NULL ) {
2007-08-15 14:29:47 +04:00
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
2007-07-13 05:22:09 +04:00
END_PROFILE ( SMBtcon ) ;
2007-08-15 14:29:47 +04:00
return ;
2007-07-13 05:22:09 +04:00
}
2014-02-26 23:16:26 +04:00
p2 = strrchr_m ( service_buf , ' \\ ' ) ;
if ( p2 ) {
service = p2 + 1 ;
2002-08-17 19:27:10 +04:00
} else {
service = service_buf ;
2001-03-13 09:55:47 +03:00
}
2014-09-15 05:47:41 +04:00
conn = make_connection ( req , now , service , dev ,
2009-05-26 18:38:45 +04:00
req - > vuid , & nt_status ) ;
2008-01-04 23:56:23 +03:00
req - > conn = conn ;
2001-10-31 15:28:40 +03:00
1998-08-14 21:38:29 +04:00
if ( ! conn ) {
2007-08-15 14:29:47 +04:00
reply_nterror ( req , nt_status ) ;
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBtcon ) ;
2007-08-15 14:29:47 +04:00
return ;
1998-08-14 21:38:29 +04:00
}
2007-07-13 05:22:09 +04:00
2022-04-05 05:53:20 +03:00
reply_smb1_outbuf ( req , 2 , 0 ) ;
2014-05-21 12:27:50 +04:00
SSVAL ( req - > outbuf , smb_vwv0 , xconn - > smb1 . negprot . max_recv ) ;
2007-08-15 14:29:47 +04:00
SSVAL ( req - > outbuf , smb_vwv1 , conn - > cnum ) ;
SSVAL ( req - > outbuf , smb_tid , conn - > cnum ) ;
2007-07-13 05:22:09 +04:00
2007-08-25 23:47:57 +04:00
DEBUG ( 3 , ( " tcon service=%s cnum=%d \n " ,
2001-09-15 16:55:59 +04:00
service , conn - > cnum ) ) ;
2007-07-13 05:22:09 +04:00
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBtcon ) ;
2007-08-15 14:29:47 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
1999-12-13 16:27:58 +03:00
Reply to a tcon and X .
2006-06-20 06:38:28 +04:00
conn POINTER CAN BE NULL HERE !
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-06-22 04:57:59 +04:00
2008-01-05 02:37:24 +03:00
void reply_tcon_and_X ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2019-11-07 13:01:05 +03:00
const struct loadparm_substitution * lp_sub =
loadparm_s3_global_substitution ( ) ;
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
2008-11-01 19:35:48 +03:00
const char * service = NULL ;
2007-09-11 22:31:29 +04:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
2017-02-17 22:59:54 +03:00
/* what the client thinks the device is */
2007-07-13 05:22:09 +04:00
char * client_devicetype = NULL ;
2003-03-28 01:27:53 +03:00
/* what the server tells the client the share represents */
const char * server_devicetype ;
2001-09-24 03:07:53 +04:00
NTSTATUS nt_status ;
2007-07-23 15:38:29 +04:00
int passlen ;
2007-07-13 05:22:09 +04:00
char * path = NULL ;
2014-02-26 23:16:26 +04:00
const uint8_t * p ;
const char * q ;
2012-08-03 10:42:43 +04:00
uint16_t tcon_flags ;
struct smbXsrv_session * session = NULL ;
NTTIME now = timeval_to_nttime ( & req - > request_time ) ;
bool session_key_updated = false ;
2012-08-03 10:44:39 +04:00
uint16_t optional_support = 0 ;
2014-06-11 17:12:32 +04:00
struct smbXsrv_connection * xconn = req - > xconn ;
2001-10-31 13:46:25 +03:00
2007-07-13 05:22:09 +04:00
START_PROFILE ( SMBtconX ) ;
1998-06-10 23:45:13 +04:00
2007-07-23 15:38:29 +04:00
if ( req - > wct < 4 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBtconX ) ;
return ;
}
2008-11-02 14:20:47 +03:00
passlen = SVAL ( req - > vwv + 3 , 0 ) ;
tcon_flags = SVAL ( req - > vwv + 2 , 0 ) ;
2007-07-23 15:38:29 +04:00
1998-08-14 21:38:29 +04:00
/* we might have to close an old one */
2012-08-01 13:48:30 +04:00
if ( ( tcon_flags & TCONX_FLAG_DISCONNECT_TID ) & & conn ) {
2012-03-28 18:14:09 +04:00
struct smbXsrv_tcon * tcon ;
NTSTATUS status ;
tcon = conn - > tcon ;
2008-01-04 23:56:23 +03:00
req - > conn = NULL ;
2008-01-05 02:37:24 +03:00
conn = NULL ;
2012-03-28 18:14:09 +04:00
/*
* TODO : cancel all outstanding requests on the tcon
*/
status = smbXsrv_tcon_disconnect ( tcon , req - > vuid ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " reply_tcon_and_X: "
" smbXsrv_tcon_disconnect() failed: %s \n " ,
nt_errstr ( status ) ) ) ;
/*
* If we hit this case , there is something completely
* wrong , so we better disconnect the transport connection .
*/
END_PROFILE ( SMBtconX ) ;
exit_server ( __location__ " : smbXsrv_tcon_disconnect failed " ) ;
return ;
}
TALLOC_FREE ( tcon ) ;
2017-09-20 02:11:33 +03:00
/*
* This tree id is gone . Make sure we can ' t re - use it
* by accident .
*/
req - > tid = 0 ;
1998-08-14 21:38:29 +04:00
}
1998-06-10 23:45:13 +04:00
2008-11-01 18:24:42 +03:00
if ( ( passlen > MAX_PASS_LEN ) | | ( passlen > = req - > buflen ) ) {
2009-12-21 22:16:38 +03:00
reply_force_doserror ( req , ERRDOS , ERRbuftoosmall ) ;
2007-07-23 15:38:29 +04:00
END_PROFILE ( SMBtconX ) ;
return ;
1998-08-14 21:38:29 +04:00
}
2007-07-13 05:22:09 +04:00
2014-05-21 12:27:50 +04:00
if ( xconn - > smb1 . negprot . encrypted_passwords ) {
2014-02-26 23:16:26 +04:00
p = req - > buf + passlen ;
2001-10-31 13:46:25 +03:00
} else {
2014-02-26 23:16:26 +04:00
p = req - > buf + passlen + 1 ;
2001-10-31 13:46:25 +03:00
}
2008-11-02 03:07:46 +03:00
p + = srvstr_pull_req_talloc ( ctx , req , & path , p , STR_TERMINATE ) ;
2007-07-13 05:22:09 +04:00
if ( path = = NULL ) {
2007-07-23 15:38:29 +04:00
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
2007-07-13 05:22:09 +04:00
END_PROFILE ( SMBtconX ) ;
2007-07-23 15:38:29 +04:00
return ;
2007-07-13 05:22:09 +04:00
}
1996-05-04 11:50:46 +04:00
2001-08-22 17:08:01 +04:00
/*
* the service name can be either : \ \ server \ share
* or share directly like on the DELL PowerVault 705
*/
2007-07-13 05:22:09 +04:00
if ( * path = = ' \\ ' ) {
2001-08-22 17:08:01 +04:00
q = strchr_m ( path + 2 , ' \\ ' ) ;
if ( ! q ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_BAD_NETWORK_NAME ) ;
2001-08-22 17:08:01 +04:00
END_PROFILE ( SMBtconX ) ;
2007-07-23 15:38:29 +04:00
return ;
2001-08-22 17:08:01 +04:00
}
2007-07-13 05:22:09 +04:00
service = q + 1 ;
} else {
service = path ;
}
2007-07-23 15:38:29 +04:00
p + = srvstr_pull_talloc ( ctx , req - > inbuf , req - > flags2 ,
& client_devicetype , p ,
2008-11-02 03:21:53 +03:00
MIN ( 6 , smbreq_bufrem ( req , p ) ) , STR_ASCII ) ;
2007-07-13 05:22:09 +04:00
if ( client_devicetype = = NULL ) {
2007-07-23 15:38:29 +04:00
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
2007-07-13 05:22:09 +04:00
END_PROFILE ( SMBtconX ) ;
2007-07-23 15:38:29 +04:00
return ;
2000-10-06 07:21:49 +04:00
}
1999-12-13 16:27:58 +03:00
2003-03-28 01:27:53 +03:00
DEBUG ( 4 , ( " Client requested device type [%s] for share [%s] \n " , client_devicetype , service ) ) ;
1998-12-01 01:42:13 +03:00
2014-06-11 17:12:32 +04:00
nt_status = smb1srv_session_lookup ( xconn ,
2012-08-03 10:42:43 +04:00
req - > vuid , now , & session ) ;
if ( NT_STATUS_EQUAL ( nt_status , NT_STATUS_USER_SESSION_DELETED ) ) {
reply_force_doserror ( req , ERRSRV , ERRbaduid ) ;
END_PROFILE ( SMBtconX ) ;
return ;
}
if ( NT_STATUS_EQUAL ( nt_status , NT_STATUS_NETWORK_SESSION_EXPIRED ) ) {
reply_nterror ( req , nt_status ) ;
END_PROFILE ( SMBtconX ) ;
return ;
}
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
reply_nterror ( req , NT_STATUS_INVALID_HANDLE ) ;
END_PROFILE ( SMBtconX ) ;
return ;
}
if ( session - > global - > auth_session_info = = NULL ) {
reply_nterror ( req , NT_STATUS_INVALID_HANDLE ) ;
END_PROFILE ( SMBtconX ) ;
return ;
}
/*
* If there is no application key defined yet
* we create one .
*
* This means we setup the application key on the
* first tcon that happens via the given session .
*
* Once the application key is defined , it does not
* change any more .
*/
2021-03-06 00:40:43 +03:00
if ( session - > global - > application_key_blob . length = = 0 & &
2019-03-13 20:07:17 +03:00
smb2_signing_key_valid ( session - > global - > signing_key ) )
2012-08-03 10:42:43 +04:00
{
struct smbXsrv_session * x = session ;
struct auth_session_info * session_info =
session - > global - > auth_session_info ;
uint8_t session_key [ 16 ] ;
ZERO_STRUCT ( session_key ) ;
2019-03-13 20:07:17 +03:00
memcpy ( session_key , x - > global - > signing_key - > blob . data ,
MIN ( x - > global - > signing_key - > blob . length , sizeof ( session_key ) ) ) ;
2012-08-03 10:42:43 +04:00
/*
* The application key is truncated / padded to 16 bytes
*/
2021-03-06 00:40:43 +03:00
x - > global - > application_key_blob = data_blob_talloc ( x - > global ,
2012-08-03 10:42:43 +04:00
session_key ,
sizeof ( session_key ) ) ;
ZERO_STRUCT ( session_key ) ;
2021-03-06 00:40:43 +03:00
if ( x - > global - > application_key_blob . data = = NULL ) {
2012-08-03 10:42:43 +04:00
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
END_PROFILE ( SMBtconX ) ;
return ;
}
2021-03-06 00:40:43 +03:00
talloc_keep_secret ( x - > global - > application_key_blob . data ) ;
2012-08-03 10:42:43 +04:00
2012-08-03 10:44:39 +04:00
if ( tcon_flags & TCONX_FLAG_EXTENDED_SIGNATURES ) {
2019-04-11 11:29:04 +03:00
NTSTATUS status ;
2022-03-08 06:41:31 +03:00
status = smb1_key_derivation ( x - > global - > application_key_blob . data ,
2021-03-06 00:40:43 +03:00
x - > global - > application_key_blob . length ,
x - > global - > application_key_blob . data ) ;
2019-04-11 11:29:04 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2022-03-08 06:41:31 +03:00
DBG_ERR ( " smb1_key_derivation failed: %s \n " ,
2019-04-11 11:29:04 +03:00
nt_errstr ( status ) ) ;
2019-09-20 18:37:28 +03:00
END_PROFILE ( SMBtconX ) ;
2019-04-11 11:29:04 +03:00
return ;
}
2012-08-03 10:44:39 +04:00
optional_support | = SMB_EXTENDED_SIGNATURES ;
}
2012-08-03 10:42:43 +04:00
/*
* Place the application key into the session_info
*/
data_blob_clear_free ( & session_info - > session_key ) ;
session_info - > session_key = data_blob_dup_talloc ( session_info ,
2021-03-06 00:40:43 +03:00
x - > global - > application_key_blob ) ;
2012-08-03 10:42:43 +04:00
if ( session_info - > session_key . data = = NULL ) {
2021-03-06 00:40:43 +03:00
data_blob_clear_free ( & x - > global - > application_key_blob ) ;
2012-08-03 10:42:43 +04:00
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
END_PROFILE ( SMBtconX ) ;
return ;
}
2021-03-06 00:40:43 +03:00
talloc_keep_secret ( session_info - > session_key . data ) ;
2012-08-03 10:42:43 +04:00
session_key_updated = true ;
}
2014-09-15 05:47:41 +04:00
conn = make_connection ( req , now , service , client_devicetype ,
2007-07-23 15:38:29 +04:00
req - > vuid , & nt_status ) ;
2008-01-04 23:56:23 +03:00
req - > conn = conn ;
2007-07-13 05:22:09 +04:00
2000-10-06 07:21:49 +04:00
if ( ! conn ) {
2012-08-03 10:42:43 +04:00
if ( session_key_updated ) {
struct smbXsrv_session * x = session ;
struct auth_session_info * session_info =
session - > global - > auth_session_info ;
2021-03-06 00:40:43 +03:00
data_blob_clear_free ( & x - > global - > application_key_blob ) ;
2012-08-03 10:42:43 +04:00
data_blob_clear_free ( & session_info - > session_key ) ;
}
2007-07-23 15:38:29 +04:00
reply_nterror ( req , nt_status ) ;
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBtconX ) ;
2007-07-23 15:38:29 +04:00
return ;
2000-10-06 07:21:49 +04:00
}
1997-08-31 18:14:22 +04:00
2003-03-28 01:27:53 +03:00
if ( IS_IPC ( conn ) )
server_devicetype = " IPC " ;
else if ( IS_PRINT ( conn ) )
2003-04-12 03:28:15 +04:00
server_devicetype = " LPT1: " ;
2007-07-13 05:22:09 +04:00
else
2003-03-28 01:27:53 +03:00
server_devicetype = " A: " ;
2023-05-25 08:50:43 +03:00
if ( xconn - > protocol < PROTOCOL_NT1 ) {
2022-04-05 05:53:20 +03:00
reply_smb1_outbuf ( req , 2 , 0 ) ;
2007-07-23 15:38:29 +04:00
if ( message_push_string ( & req - > outbuf , server_devicetype ,
STR_TERMINATE | STR_ASCII ) = = - 1 ) {
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
END_PROFILE ( SMBtconX ) ;
return ;
}
1998-08-14 21:38:29 +04:00
} else {
2001-03-13 06:45:09 +03:00
/* NT sets the fstype of IPC$ to the null string */
2014-01-16 06:58:31 +04:00
const char * fstype = IS_IPC ( conn ) ? " " : lp_fstype ( SNUM ( conn ) ) ;
2007-07-13 05:22:09 +04:00
2007-04-07 09:49:24 +04:00
if ( tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE ) {
/* Return permissions. */
2015-04-27 02:02:55 +03:00
uint32_t perm1 = 0 ;
uint32_t perm2 = 0 ;
2007-04-07 09:49:24 +04:00
2022-04-05 05:53:20 +03:00
reply_smb1_outbuf ( req , 7 , 0 ) ;
2007-04-07 09:49:24 +04:00
if ( IS_IPC ( conn ) ) {
perm1 = FILE_ALL_ACCESS ;
perm2 = FILE_ALL_ACCESS ;
} else {
2011-07-11 18:12:57 +04:00
perm1 = conn - > share_access ;
2007-04-07 09:49:24 +04:00
}
2007-07-23 15:38:29 +04:00
SIVAL ( req - > outbuf , smb_vwv3 , perm1 ) ;
SIVAL ( req - > outbuf , smb_vwv5 , perm2 ) ;
2007-04-07 09:49:24 +04:00
} else {
2022-04-05 05:53:20 +03:00
reply_smb1_outbuf ( req , 3 , 0 ) ;
2007-04-07 09:49:24 +04:00
}
1997-08-31 18:14:22 +04:00
2007-07-23 15:38:29 +04:00
if ( ( message_push_string ( & req - > outbuf , server_devicetype ,
STR_TERMINATE | STR_ASCII ) = = - 1 )
| | ( message_push_string ( & req - > outbuf , fstype ,
STR_TERMINATE ) = = - 1 ) ) {
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
END_PROFILE ( SMBtconX ) ;
return ;
}
2007-07-13 05:22:09 +04:00
1998-09-20 19:48:10 +04:00
/* what does setting this bit do? It is set by NT4 and
may affect the ability to autorun mounted cdroms */
2012-08-01 14:01:07 +04:00
optional_support | = SMB_SUPPORT_SEARCH_BITS ;
optional_support | =
( lp_csc_policy ( SNUM ( conn ) ) < < SMB_CSC_POLICY_SHIFT ) ;
2007-07-13 05:22:09 +04:00
2008-10-18 21:41:12 +04:00
if ( lp_msdfs_root ( SNUM ( conn ) ) & & lp_host_msdfs ( ) ) {
DEBUG ( 2 , ( " Serving %s as a Dfs root \n " ,
2019-11-07 13:01:05 +03:00
lp_servicename ( ctx , lp_sub , SNUM ( conn ) ) ) ) ;
2012-08-01 14:01:07 +04:00
optional_support | = SMB_SHARE_IN_DFS ;
2008-10-18 21:41:12 +04:00
}
2012-08-01 14:01:07 +04:00
SSVAL ( req - > outbuf , smb_vwv2 , optional_support ) ;
1998-08-14 21:38:29 +04:00
}
2000-03-09 01:14:30 +03:00
2012-02-26 19:49:09 +04:00
SSVAL ( req - > outbuf , smb_vwv0 , 0xff ) ; /* andx chain ends */
SSVAL ( req - > outbuf , smb_vwv1 , 0 ) ; /* no andx offset */
2007-07-13 05:22:09 +04:00
2001-09-15 16:55:59 +04:00
DEBUG ( 3 , ( " tconX service=%s \n " ,
service ) ) ;
2007-07-13 05:22:09 +04:00
1998-08-14 21:38:29 +04:00
/* set the incoming and outgoing tid to the just created one */
2011-05-05 21:41:59 +04:00
SSVAL ( discard_const_p ( uint8_t , req - > inbuf ) , smb_tid , conn - > cnum ) ;
2007-07-23 15:38:29 +04:00
SSVAL ( req - > outbuf , smb_tid , conn - > cnum ) ;
1996-05-04 11:50:46 +04:00
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBtconX ) ;
2007-07-23 15:38:29 +04:00
2009-07-16 00:59:11 +04:00
req - > tid = conn - > cnum ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to an unknown type .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2015-04-27 02:02:55 +03:00
void reply_unknown_new ( struct smb_request * req , uint8_t type )
2007-07-23 13:36:09 +04:00
{
DEBUG ( 0 , ( " unknown command type (%s): type=%d (0x%X) \n " ,
smb_fn_name ( type ) , type , type ) ) ;
2009-12-21 22:16:38 +03:00
reply_force_doserror ( req , ERRSRV , ERRunknownsmb ) ;
2007-07-23 13:36:09 +04:00
return ;
}
1996-05-04 11:50:46 +04:00
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to an ioctl .
2006-06-20 06:38:28 +04:00
conn POINTER CAN BE NULL HERE !
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2008-01-05 02:37:24 +03:00
void reply_ioctl ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2019-11-07 13:01:05 +03:00
const struct loadparm_substitution * lp_sub =
loadparm_s3_global_substitution ( ) ;
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
2015-04-27 02:02:55 +03:00
uint16_t device ;
uint16_t function ;
uint32_t ioctl_code ;
2007-08-15 01:13:05 +04:00
int replysize ;
1999-12-13 16:27:58 +03:00
char * p ;
2007-08-15 01:13:05 +04:00
2000-10-06 07:21:49 +04:00
START_PROFILE ( SMBioctl ) ;
1999-12-13 16:27:58 +03:00
2007-08-15 01:13:05 +04:00
if ( req - > wct < 3 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBioctl ) ;
return ;
}
2008-11-02 14:20:47 +03:00
device = SVAL ( req - > vwv + 1 , 0 ) ;
function = SVAL ( req - > vwv + 2 , 0 ) ;
2007-08-15 01:13:05 +04:00
ioctl_code = ( device < < 16 ) + function ;
1999-12-13 16:27:58 +03:00
DEBUG ( 4 , ( " Received IOCTL (code 0x%x) \n " , ioctl_code ) ) ;
2002-09-25 19:19:00 +04:00
switch ( ioctl_code ) {
1999-12-13 16:27:58 +03:00
case IOCTL_QUERY_JOB_INFO :
2007-08-15 01:13:05 +04:00
replysize = 32 ;
break ;
1999-12-13 16:27:58 +03:00
default :
2009-12-21 22:16:38 +03:00
reply_force_doserror ( req , ERRSRV , ERRnosupport ) ;
2007-08-15 01:13:05 +04:00
END_PROFILE ( SMBioctl ) ;
return ;
1999-12-13 16:27:58 +03:00
}
2022-04-05 05:53:20 +03:00
reply_smb1_outbuf ( req , 8 , replysize + 1 ) ;
2007-08-15 01:13:05 +04:00
SSVAL ( req - > outbuf , smb_vwv1 , replysize ) ; /* Total data bytes returned */
SSVAL ( req - > outbuf , smb_vwv5 , replysize ) ; /* Data bytes this buffer */
SSVAL ( req - > outbuf , smb_vwv6 , 52 ) ; /* Offset to data */
2007-09-08 00:57:01 +04:00
p = smb_buf ( req - > outbuf ) ;
memset ( p , ' \0 ' , replysize + 1 ) ; /* valgrind-safe. */
p + = 1 ; /* Allow for alignment */
1999-12-13 16:27:58 +03:00
2002-09-25 19:19:00 +04:00
switch ( ioctl_code ) {
2023-07-18 12:30:18 +03:00
case IOCTL_QUERY_JOB_INFO :
2002-09-25 19:19:00 +04:00
{
2014-08-26 04:11:58 +04:00
NTSTATUS status ;
size_t len = 0 ;
2008-10-09 17:25:17 +04:00
files_struct * fsp = file_fsp (
2008-11-02 14:20:47 +03:00
req , SVAL ( req - > vwv + 0 , 0 ) ) ;
2003-09-09 00:27:28 +04:00
if ( ! fsp ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_INVALID_HANDLE ) ;
2003-09-09 00:27:28 +04:00
END_PROFILE ( SMBioctl ) ;
2007-08-15 01:13:05 +04:00
return ;
2003-09-09 00:27:28 +04:00
}
2010-04-24 01:26:33 +04:00
/* Job number */
2012-06-05 10:33:53 +04:00
SSVAL ( p , 0 , print_spool_rap_jobid ( fsp - > print_file ) ) ;
2014-08-26 04:11:58 +04:00
status = srvstr_push ( ( char * ) req - > outbuf , req - > flags2 , p + 2 ,
2011-06-09 09:31:03 +04:00
lp_netbios_name ( ) , 15 ,
2014-08-26 04:11:58 +04:00
STR_TERMINATE | STR_ASCII , & len ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
reply_nterror ( req , status ) ;
END_PROFILE ( SMBioctl ) ;
return ;
}
2004-05-22 09:01:25 +04:00
if ( conn ) {
2014-08-26 04:11:58 +04:00
status = srvstr_push ( ( char * ) req - > outbuf , req - > flags2 ,
2012-07-18 09:37:23 +04:00
p + 18 ,
lp_servicename ( talloc_tos ( ) ,
2019-11-07 13:01:05 +03:00
lp_sub ,
2012-07-18 09:37:23 +04:00
SNUM ( conn ) ) ,
2014-08-26 04:11:58 +04:00
13 , STR_TERMINATE | STR_ASCII , & len ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
reply_nterror ( req , status ) ;
END_PROFILE ( SMBioctl ) ;
return ;
}
2007-09-08 00:57:01 +04:00
} else {
2007-08-15 01:13:05 +04:00
memset ( p + 18 , 0 , 13 ) ;
}
2002-09-25 19:19:00 +04:00
break ;
}
1999-12-13 16:27:58 +03:00
}
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBioctl ) ;
2007-08-15 01:13:05 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
2007-01-14 01:10:18 +03:00
Strange checkpath NTSTATUS mapping .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2008-11-03 00:20:48 +03:00
static NTSTATUS map_checkpath_error ( uint16_t flags2 , NTSTATUS status )
2007-01-14 01:10:18 +03:00
{
/* Strange DOS error code semantics only for checkpath... */
2008-11-03 00:20:48 +03:00
if ( ! ( flags2 & FLAGS2_32_BIT_ERROR_CODES ) ) {
2007-01-14 01:10:18 +03:00
if ( NT_STATUS_EQUAL ( NT_STATUS_OBJECT_NAME_INVALID , status ) ) {
/* We need to map to ERRbadpath */
return NT_STATUS_OBJECT_PATH_NOT_FOUND ;
}
}
return status ;
}
2007-09-12 03:57:59 +04:00
2007-01-14 01:10:18 +03:00
/****************************************************************************
Reply to a checkpath .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-01-05 02:37:24 +03:00
void reply_checkpath ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
struct smb_filename * smb_fname = NULL ;
2007-09-08 00:57:01 +04:00
char * name = NULL ;
2003-08-13 07:28:06 +04:00
NTSTATUS status ;
2022-07-28 02:21:52 +03:00
struct files_struct * dirfsp = NULL ;
2017-05-18 22:08:00 +03:00
uint32_t ucf_flags = ucf_flags_from_smb_request ( req ) ;
2022-07-28 02:21:52 +03:00
NTTIME twrp = 0 ;
2007-09-11 22:31:29 +04:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
2003-08-13 07:28:06 +04:00
2007-01-14 01:10:18 +03:00
START_PROFILE ( SMBcheckpath ) ;
2001-03-13 06:45:09 +03:00
2008-11-02 02:59:03 +03:00
srvstr_get_path_req ( ctx , req , & name , ( const char * ) req - > buf + 1 ,
STR_TERMINATE , & status ) ;
2003-10-09 03:21:36 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2008-11-03 00:20:48 +03:00
status = map_checkpath_error ( req - > flags2 , status ) ;
2007-07-23 16:03:58 +04:00
reply_nterror ( req , status ) ;
2007-01-14 01:10:18 +03:00
END_PROFILE ( SMBcheckpath ) ;
2007-07-23 16:03:58 +04:00
return ;
2003-10-09 03:21:36 +04:00
}
2003-08-13 07:28:06 +04:00
2009-06-19 00:13:38 +04:00
DEBUG ( 3 , ( " reply_checkpath %s mode=%d \n " , name , ( int ) SVAL ( req - > vwv + 0 , 0 ) ) ) ;
2022-07-28 02:21:52 +03:00
if ( ucf_flags & UCF_GMT_PATHNAME ) {
2022-08-04 20:02:15 +03:00
extract_snapshot_token ( name , & twrp ) ;
2022-07-28 02:21:52 +03:00
}
2023-03-30 16:45:55 +03:00
status = smb1_strip_dfs_path ( ctx , & ucf_flags , & name ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
reply_nterror ( req , status ) ;
goto out ;
}
2022-07-28 02:21:52 +03:00
status = filename_convert_dirfsp ( ctx ,
conn ,
name ,
ucf_flags ,
twrp ,
& dirfsp ,
& smb_fname ) ;
2007-03-12 20:55:24 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
if ( NT_STATUS_EQUAL ( status , NT_STATUS_PATH_NOT_COVERED ) ) {
2007-07-23 16:03:58 +04:00
reply_botherror ( req , NT_STATUS_PATH_NOT_COVERED ,
ERRSRV , ERRbadpath ) ;
2007-03-12 20:55:24 +03:00
END_PROFILE ( SMBcheckpath ) ;
2007-07-23 16:03:58 +04:00
return ;
2007-03-12 20:55:24 +03:00
}
goto path_err ;
2007-03-08 01:12:58 +03:00
}
2000-03-09 01:14:30 +03:00
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
if ( ! VALID_STAT ( smb_fname - > st ) & &
2009-06-23 02:26:56 +04:00
( SMB_VFS_STAT ( conn , smb_fname ) ! = 0 ) ) {
DEBUG ( 3 , ( " reply_checkpath: stat of %s failed (%s) \n " ,
smb_fname_str_dbg ( smb_fname ) , strerror ( errno ) ) ) ;
2007-01-17 05:09:37 +03:00
status = map_nt_error_from_unix ( errno ) ;
goto path_err ;
}
1997-10-04 00:36:06 +04:00
2009-05-14 17:34:42 +04:00
if ( ! S_ISDIR ( smb_fname - > st . st_ex_mode ) ) {
2007-07-23 16:03:58 +04:00
reply_botherror ( req , NT_STATUS_NOT_A_DIRECTORY ,
ERRDOS , ERRbadpath ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2002-09-25 19:19:00 +04:00
}
1998-08-01 02:39:15 +04:00
2022-04-05 05:53:20 +03:00
reply_smb1_outbuf ( req , 0 , 0 ) ;
2007-01-17 05:09:37 +03:00
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
path_err :
2007-01-17 05:09:37 +03:00
/* We special case this - as when a Windows machine
is parsing a path is steps through the components
one at a time - if a component fails it expects
ERRbadpath , not ERRbadfile .
*/
2008-11-03 00:20:48 +03:00
status = map_checkpath_error ( req - > flags2 , status ) ;
2007-07-23 16:03:58 +04:00
if ( NT_STATUS_EQUAL ( status , NT_STATUS_OBJECT_NAME_NOT_FOUND ) ) {
2007-01-17 05:09:37 +03:00
/*
* Windows returns different error codes if
* the parent directory is valid but not the
* last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
* for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
* if the path is invalid .
*/
2007-07-23 16:03:58 +04:00
reply_botherror ( req , NT_STATUS_OBJECT_NAME_NOT_FOUND ,
ERRDOS , ERRbadpath ) ;
2009-06-23 02:26:56 +04:00
goto out ;
2007-01-17 05:09:37 +03:00
}
2007-07-23 16:03:58 +04:00
reply_nterror ( req , status ) ;
2009-06-23 02:26:56 +04:00
out :
TALLOC_FREE ( smb_fname ) ;
END_PROFILE ( SMBcheckpath ) ;
return ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a getatr .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2008-01-05 02:37:24 +03:00
void reply_getatr ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2023-05-25 08:50:43 +03:00
struct smbXsrv_connection * xconn = req - > xconn ;
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
struct smb_filename * smb_fname = NULL ;
2007-09-08 00:57:01 +04:00
char * fname = NULL ;
2002-12-04 02:57:45 +03:00
int mode = 0 ;
2012-04-05 08:53:08 +04:00
off_t size = 0 ;
2002-12-04 02:57:45 +03:00
time_t mtime = 0 ;
2008-11-01 19:35:48 +03:00
const char * p ;
2003-10-09 03:21:36 +04:00
NTSTATUS status ;
2007-09-11 22:31:29 +04:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
2003-10-09 03:21:36 +04:00
2002-12-04 02:57:45 +03:00
START_PROFILE ( SMBgetatr ) ;
2008-11-01 19:35:48 +03:00
p = ( const char * ) req - > buf + 1 ;
2008-11-02 02:59:03 +03:00
p + = srvstr_get_path_req ( ctx , req , & fname , p , STR_TERMINATE , & status ) ;
2003-10-09 03:21:36 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-14 19:09:49 +04:00
reply_nterror ( req , status ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2003-10-09 03:21:36 +04:00
}
2002-12-04 02:57:45 +03:00
2022-06-02 16:48:37 +03:00
/*
* dos sometimes asks for a stat of " " - it returns a " hidden
* directory " under WfWg - weird!
*/
2007-09-11 22:31:29 +04:00
if ( * fname = = ' \0 ' ) {
2011-04-29 05:57:02 +04:00
mode = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY ;
2007-01-14 01:22:32 +03:00
if ( ! CAN_WRITE ( conn ) ) {
2011-04-29 05:36:14 +04:00
mode | = FILE_ATTRIBUTE_READONLY ;
2007-01-14 01:22:32 +03:00
}
2002-12-04 02:57:45 +03:00
size = 0 ;
mtime = 0 ;
} else {
2022-07-28 20:30:02 +03:00
struct files_struct * dirfsp = NULL ;
2017-05-18 22:08:00 +03:00
uint32_t ucf_flags = ucf_flags_from_smb_request ( req ) ;
2022-07-28 20:30:02 +03:00
NTTIME twrp = 0 ;
2022-05-11 19:13:13 +03:00
bool ask_sharemode ;
2022-07-28 20:30:02 +03:00
if ( ucf_flags & UCF_GMT_PATHNAME ) {
2022-08-04 20:02:15 +03:00
extract_snapshot_token ( fname , & twrp ) ;
2022-07-28 20:30:02 +03:00
}
2023-03-30 17:01:17 +03:00
status = smb1_strip_dfs_path ( ctx , & ucf_flags , & fname ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
reply_nterror ( req , status ) ;
goto out ;
}
2022-07-28 20:30:02 +03:00
status = filename_convert_dirfsp ( ctx ,
conn ,
fname ,
ucf_flags ,
twrp ,
& dirfsp ,
& smb_fname ) ;
2007-01-17 05:09:37 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2009-06-19 00:13:38 +04:00
if ( NT_STATUS_EQUAL ( status , NT_STATUS_PATH_NOT_COVERED ) ) {
reply_botherror ( req , NT_STATUS_PATH_NOT_COVERED ,
ERRSRV , ERRbadpath ) ;
goto out ;
}
2007-08-14 19:09:49 +04:00
reply_nterror ( req , status ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2007-01-17 05:09:37 +03:00
}
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
if ( ! VALID_STAT ( smb_fname - > st ) & &
2009-06-23 02:26:56 +04:00
( SMB_VFS_STAT ( conn , smb_fname ) ! = 0 ) ) {
DEBUG ( 3 , ( " reply_getatr: stat of %s failed (%s) \n " ,
smb_fname_str_dbg ( smb_fname ) ,
strerror ( errno ) ) ) ;
2009-07-11 05:23:00 +04:00
reply_nterror ( req , map_nt_error_from_unix ( errno ) ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2002-12-04 02:57:45 +03:00
}
2007-01-17 05:09:37 +03:00
2020-10-19 21:41:18 +03:00
mode = fdos_mode ( smb_fname - > fsp ) ;
2009-05-14 17:34:42 +04:00
size = smb_fname - > st . st_ex_size ;
2009-07-09 04:51:35 +04:00
2022-05-11 19:13:13 +03:00
ask_sharemode = fsp_search_ask_sharemode ( smb_fname - > fsp ) ;
2009-07-09 04:51:35 +04:00
if ( ask_sharemode ) {
struct timespec write_time_ts ;
struct file_id fileid ;
ZERO_STRUCT ( write_time_ts ) ;
fileid = vfs_file_id_from_sbuf ( conn , & smb_fname - > st ) ;
2011-01-26 00:57:38 +03:00
get_file_infos ( fileid , 0 , NULL , & write_time_ts ) ;
2019-12-02 18:30:50 +03:00
if ( ! is_omit_timespec ( & write_time_ts ) ) {
2009-07-09 05:05:30 +04:00
update_stat_ex_mtime ( & smb_fname - > st , write_time_ts ) ;
2009-07-09 04:51:35 +04:00
}
}
2009-05-14 17:34:42 +04:00
mtime = convert_timespec_to_time_t ( smb_fname - > st . st_ex_mtime ) ;
2011-04-29 05:57:02 +04:00
if ( mode & FILE_ATTRIBUTE_DIRECTORY ) {
2007-01-17 05:09:37 +03:00
size = 0 ;
}
2002-12-04 02:57:45 +03:00
}
1996-05-04 11:50:46 +04:00
2022-04-05 05:53:20 +03:00
reply_smb1_outbuf ( req , 10 , 0 ) ;
2007-08-14 19:09:49 +04:00
SSVAL ( req - > outbuf , smb_vwv0 , mode ) ;
2005-11-05 07:21:55 +03:00
if ( lp_dos_filetime_resolution ( SNUM ( conn ) ) ) {
2007-08-14 19:09:49 +04:00
srv_put_dos_date3 ( ( char * ) req - > outbuf , smb_vwv1 , mtime & ~ 1 ) ;
2005-11-05 07:21:55 +03:00
} else {
2007-08-14 19:09:49 +04:00
srv_put_dos_date3 ( ( char * ) req - > outbuf , smb_vwv1 , mtime ) ;
2005-11-05 07:21:55 +03:00
}
2015-05-03 07:01:14 +03:00
SIVAL ( req - > outbuf , smb_vwv3 , ( uint32_t ) size ) ;
1996-05-04 11:50:46 +04:00
2023-05-25 08:50:43 +03:00
if ( xconn - > protocol > = PROTOCOL_NT1 ) {
2007-08-14 19:09:49 +04:00
SSVAL ( req - > outbuf , smb_flg2 ,
SVAL ( req - > outbuf , smb_flg2 ) | FLAGS2_IS_LONG_NAME ) ;
2005-11-05 07:21:55 +03:00
}
2008-10-19 17:30:12 +04:00
2009-06-23 02:26:56 +04:00
DEBUG ( 3 , ( " reply_getatr: name=%s mode=%d size=%u \n " ,
smb_fname_str_dbg ( smb_fname ) , mode , ( unsigned int ) size ) ) ;
2007-09-12 03:57:59 +04:00
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
out :
2009-05-25 00:13:07 +04:00
TALLOC_FREE ( smb_fname ) ;
2009-06-23 02:26:56 +04:00
TALLOC_FREE ( fname ) ;
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBgetatr ) ;
2007-08-14 19:09:49 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a setatr .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2008-01-05 02:37:24 +03:00
void reply_setatr ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2009-01-24 01:40:19 +03:00
struct smb_file_time ft ;
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
struct smb_filename * smb_fname = NULL ;
2022-07-28 20:33:31 +03:00
struct files_struct * dirfsp = NULL ;
2007-09-08 00:57:01 +04:00
char * fname = NULL ;
2002-12-04 02:57:45 +03:00
int mode ;
time_t mtime ;
2008-11-01 19:35:48 +03:00
const char * p ;
2003-10-09 03:21:36 +04:00
NTSTATUS status ;
2017-05-18 22:08:00 +03:00
uint32_t ucf_flags = ucf_flags_from_smb_request ( req ) ;
2022-07-28 20:33:31 +03:00
NTTIME twrp = 0 ;
2007-09-11 22:31:29 +04:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
2002-12-04 02:57:45 +03:00
START_PROFILE ( SMBsetatr ) ;
2019-12-02 18:30:50 +03:00
init_smb_file_time ( & ft ) ;
2002-12-04 02:57:45 +03:00
2007-08-14 19:26:54 +04:00
if ( req - > wct < 2 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2007-08-14 19:26:54 +04:00
}
2008-11-01 19:35:48 +03:00
p = ( const char * ) req - > buf + 1 ;
2008-11-02 02:59:03 +03:00
p + = srvstr_get_path_req ( ctx , req , & fname , p , STR_TERMINATE , & status ) ;
2003-10-09 03:21:36 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-14 19:26:54 +04:00
reply_nterror ( req , status ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2003-10-09 03:21:36 +04:00
}
2022-07-28 20:33:31 +03:00
if ( ucf_flags & UCF_GMT_PATHNAME ) {
2022-08-04 20:02:15 +03:00
extract_snapshot_token ( fname , & twrp ) ;
2022-07-28 20:33:31 +03:00
}
2023-03-30 17:01:42 +03:00
status = smb1_strip_dfs_path ( ctx , & ucf_flags , & fname ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
reply_nterror ( req , status ) ;
goto out ;
}
2022-07-28 20:33:31 +03:00
status = filename_convert_dirfsp ( ctx ,
conn ,
fname ,
ucf_flags ,
twrp ,
& dirfsp ,
& smb_fname ) ;
2007-03-12 20:55:24 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
if ( NT_STATUS_EQUAL ( status , NT_STATUS_PATH_NOT_COVERED ) ) {
2007-08-14 19:26:54 +04:00
reply_botherror ( req , NT_STATUS_PATH_NOT_COVERED ,
ERRSRV , ERRbadpath ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2007-03-12 20:55:24 +03:00
}
2007-08-14 19:26:54 +04:00
reply_nterror ( req , status ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2007-03-08 01:12:58 +03:00
}
2007-09-12 03:57:59 +04:00
2019-04-15 23:31:40 +03:00
if ( ISDOT ( smb_fname - > base_name ) ) {
2007-01-03 15:01:17 +03:00
/*
* Not sure here is the right place to catch this
* condition . Might be moved to somewhere else later - - vl
*/
2007-08-14 19:26:54 +04:00
reply_nterror ( req , NT_STATUS_ACCESS_DENIED ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2007-01-03 15:01:17 +03:00
}
2021-06-02 23:37:30 +03:00
if ( smb_fname - > fsp = = NULL ) {
/* Can't set access rights on a symlink. */
reply_nterror ( req , NT_STATUS_ACCESS_DENIED ) ;
goto out ;
}
2008-11-02 14:20:47 +03:00
mode = SVAL ( req - > vwv + 0 , 0 ) ;
mtime = srv_make_unix_date3 ( req - > vwv + 1 ) ;
2007-09-14 02:08:59 +04:00
2003-08-15 03:15:02 +04:00
if ( mode ! = FILE_ATTRIBUTE_NORMAL ) {
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
if ( VALID_STAT_OF_DIR ( smb_fname - > st ) )
2011-04-29 05:57:02 +04:00
mode | = FILE_ATTRIBUTE_DIRECTORY ;
2003-08-15 03:15:02 +04:00
else
2011-04-29 05:57:02 +04:00
mode & = ~ FILE_ATTRIBUTE_DIRECTORY ;
2003-08-15 03:15:02 +04:00
2021-06-08 22:24:17 +03:00
status = smbd_check_access_rights_fsp ( conn - > cwd_fsp ,
smb_fname - > fsp ,
2020-05-01 01:48:12 +03:00
false ,
FILE_WRITE_ATTRIBUTES ) ;
2011-11-16 05:29:59 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
reply_nterror ( req , status ) ;
goto out ;
}
2009-07-07 01:36:16 +04:00
if ( file_set_dosmode ( conn , smb_fname , mode , NULL ,
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
false ) ! = 0 ) {
2009-07-11 05:23:00 +04:00
reply_nterror ( req , map_nt_error_from_unix ( errno ) ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2007-01-08 16:21:43 +03:00
}
2003-08-15 03:15:02 +04:00
}
2002-12-04 02:57:45 +03:00
2019-12-02 18:30:50 +03:00
ft . mtime = time_t_to_full_timespec ( mtime ) ;
2019-04-14 11:50:10 +03:00
2020-11-04 12:09:34 +03:00
status = smb_set_file_time ( conn , smb_fname - > fsp , smb_fname , & ft , true ) ;
2011-11-16 04:49:42 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
reply_nterror ( req , status ) ;
goto out ;
}
2022-04-05 05:53:20 +03:00
reply_smb1_outbuf ( req , 0 , 0 ) ;
2008-10-19 17:30:12 +04:00
2009-07-03 00:39:20 +04:00
DEBUG ( 3 , ( " setatr name=%s mode=%d \n " , smb_fname_str_dbg ( smb_fname ) ,
mode ) ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
out :
2009-05-25 00:13:07 +04:00
TALLOC_FREE ( smb_fname ) ;
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBsetatr ) ;
2007-08-14 19:26:54 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a dskattr .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2008-01-05 02:37:24 +03:00
void reply_dskattr ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2023-05-25 08:50:43 +03:00
struct smbXsrv_connection * xconn = req - > xconn ;
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
2015-02-16 21:26:23 +03:00
uint64_t ret ;
2008-10-14 03:59:36 +04:00
uint64_t dfree , dsize , bsize ;
2016-01-14 01:09:36 +03:00
struct smb_filename smb_fname ;
2002-07-15 14:35:28 +04:00
START_PROFILE ( SMBdskattr ) ;
2016-01-14 01:09:36 +03:00
ZERO_STRUCT ( smb_fname ) ;
smb_fname . base_name = discard_const_p ( char , " . " ) ;
if ( SMB_VFS_STAT ( conn , & smb_fname ) ! = 0 ) {
reply_nterror ( req , map_nt_error_from_unix ( errno ) ) ;
DBG_WARNING ( " stat of . failed (%s) \n " , strerror ( errno ) ) ;
END_PROFILE ( SMBdskattr ) ;
return ;
}
ret = get_dfree_info ( conn , & smb_fname , & bsize , & dfree , & dsize ) ;
2015-02-16 21:26:23 +03:00
if ( ret = = ( uint64_t ) - 1 ) {
2009-07-11 05:23:00 +04:00
reply_nterror ( req , map_nt_error_from_unix ( errno ) ) ;
2005-03-16 04:41:21 +03:00
END_PROFILE ( SMBdskattr ) ;
2007-07-30 14:30:19 +04:00
return ;
2005-03-16 04:41:21 +03:00
}
2007-07-30 14:30:19 +04:00
2015-02-16 21:26:23 +03:00
/*
* Force max to fit in 16 bit fields .
*/
while ( dfree > WORDMAX | | dsize > WORDMAX | | bsize < 512 ) {
dfree / = 2 ;
dsize / = 2 ;
bsize * = 2 ;
if ( bsize > ( WORDMAX * 512 ) ) {
bsize = ( WORDMAX * 512 ) ;
if ( dsize > WORDMAX )
dsize = WORDMAX ;
if ( dfree > WORDMAX )
dfree = WORDMAX ;
break ;
}
}
2022-04-05 05:53:20 +03:00
reply_smb1_outbuf ( req , 5 , 0 ) ;
2008-10-19 17:30:12 +04:00
2023-05-25 08:50:43 +03:00
if ( xconn - > protocol < = PROTOCOL_LANMAN2 ) {
2002-07-15 14:35:28 +04:00
double total_space , free_space ;
/* we need to scale this to a number that DOS6 can handle. We
use floating point so we can handle large drives on systems
2023-07-18 12:30:18 +03:00
that don ' t have 64 bit integers
1998-08-01 02:39:15 +04:00
2002-07-15 14:35:28 +04:00
we end up displaying a maximum of 2 G to DOS systems
*/
total_space = dsize * ( double ) bsize ;
free_space = dfree * ( double ) bsize ;
1998-08-01 02:39:15 +04:00
2008-10-14 03:59:36 +04:00
dsize = ( uint64_t ) ( ( total_space + 63 * 512 ) / ( 64 * 512 ) ) ;
dfree = ( uint64_t ) ( ( free_space + 63 * 512 ) / ( 64 * 512 ) ) ;
2008-10-19 17:30:12 +04:00
2002-07-15 14:35:28 +04:00
if ( dsize > 0xFFFF ) dsize = 0xFFFF ;
if ( dfree > 0xFFFF ) dfree = 0xFFFF ;
2007-07-30 14:30:19 +04:00
SSVAL ( req - > outbuf , smb_vwv0 , dsize ) ;
SSVAL ( req - > outbuf , smb_vwv1 , 64 ) ; /* this must be 64 for dos systems */
SSVAL ( req - > outbuf , smb_vwv2 , 512 ) ; /* and this must be 512 */
SSVAL ( req - > outbuf , smb_vwv3 , dfree ) ;
2002-07-15 14:35:28 +04:00
} else {
2007-07-30 14:30:19 +04:00
SSVAL ( req - > outbuf , smb_vwv0 , dsize ) ;
SSVAL ( req - > outbuf , smb_vwv1 , bsize / 512 ) ;
SSVAL ( req - > outbuf , smb_vwv2 , 512 ) ;
SSVAL ( req - > outbuf , smb_vwv3 , dfree ) ;
2002-07-15 14:35:28 +04:00
}
DEBUG ( 3 , ( " dskattr dfree=%d \n " , ( unsigned int ) dfree ) ) ;
END_PROFILE ( SMBdskattr ) ;
2007-07-30 14:30:19 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
2014-09-08 14:41:19 +04:00
/****************************************************************************
Make a dir struct .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2023-06-07 16:16:44 +03:00
static void make_dir_struct ( TALLOC_CTX * ctx ,
2014-09-08 14:41:19 +04:00
char * buf ,
const char * mask ,
const char * fname ,
off_t size ,
2015-04-27 02:02:55 +03:00
uint32_t mode ,
2014-09-08 14:41:19 +04:00
time_t date ,
bool uc )
{
char * p ;
if ( ( mode & FILE_ATTRIBUTE_DIRECTORY ) ! = 0 ) {
size = 0 ;
}
memset ( buf + 1 , ' ' , 11 ) ;
2023-06-07 16:16:44 +03:00
if ( ( p = strchr_m ( mask , ' . ' ) ) ! = NULL ) {
char name [ p - mask + 1 ] ;
strlcpy ( name , mask , sizeof ( name ) ) ;
push_ascii ( buf + 1 , name , 8 , 0 ) ;
2014-09-08 14:41:19 +04:00
push_ascii ( buf + 9 , p + 1 , 3 , 0 ) ;
} else {
2023-06-07 16:16:44 +03:00
push_ascii ( buf + 1 , mask , 11 , 0 ) ;
2014-09-08 14:41:19 +04:00
}
memset ( buf + 21 , ' \0 ' , DIR_STRUCT_SIZE - 21 ) ;
SCVAL ( buf , 21 , mode ) ;
srv_put_dos_date ( buf , 22 , date ) ;
SSVAL ( buf , 26 , size & 0xFFFF ) ;
SSVAL ( buf , 28 , ( size > > 16 ) & 0xFFFF ) ;
/* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf.
Strange , but verified on W2K3 . Needed for OS / 2. JRA . */
push_ascii ( buf + 30 , fname , 12 , uc ? STR_UPPER : 0 ) ;
DEBUG ( 8 , ( " put name [%s] from [%s] into dir struct \n " , buf + 30 , fname ) ) ;
}
2023-05-23 10:48:24 +03:00
static bool mangle_mask_match ( connection_struct * conn ,
const char * filename ,
const char * mask )
{
char mname [ 13 ] ;
if ( ! name_to_8_3 ( filename , mname , False , conn - > params ) ) {
return False ;
}
return mask_match_search ( mname , mask , False ) ;
}
/****************************************************************************
Get an 8.3 directory entry .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static bool smbd_dirptr_8_3_match_fn ( TALLOC_CTX * ctx ,
void * private_data ,
const char * dname ,
const char * mask ,
char * * _fname )
{
connection_struct * conn = ( connection_struct * ) private_data ;
if ( ( strcmp ( mask , " *.* " ) = = 0 ) | |
mask_match_search ( dname , mask , false ) | |
mangle_mask_match ( conn , dname , mask ) ) {
char mname [ 13 ] ;
const char * fname ;
/*
* Ensure we can push the original name as UCS2 . If
* not , then just don ' t return this name .
*/
NTSTATUS status ;
size_t ret_len = 0 ;
size_t len = ( strlen ( dname ) + 2 ) * 4 ; /* Allow enough space. */
uint8_t * tmp = talloc_array ( talloc_tos ( ) , uint8_t , len ) ;
status = srvstr_push ( NULL ,
FLAGS2_UNICODE_STRINGS ,
tmp ,
dname ,
len ,
STR_TERMINATE ,
& ret_len ) ;
TALLOC_FREE ( tmp ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return false ;
}
if ( ! mangle_is_8_3 ( dname , false , conn - > params ) ) {
bool ok =
name_to_8_3 ( dname , mname , false , conn - > params ) ;
if ( ! ok ) {
return false ;
}
fname = mname ;
} else {
fname = dname ;
}
* _fname = talloc_strdup ( ctx , fname ) ;
if ( * _fname = = NULL ) {
return false ;
}
return true ;
}
return false ;
}
static bool smbd_dirptr_8_3_mode_fn ( TALLOC_CTX * ctx ,
void * private_data ,
struct files_struct * dirfsp ,
struct smb_filename * smb_fname ,
bool get_dosmode ,
uint32_t * _mode )
{
2023-06-22 16:12:25 +03:00
if ( * _mode & FILE_ATTRIBUTE_REPARSE_POINT ) {
/*
* Don ' t show symlinks / special files to old clients
*/
return false ;
}
2023-05-23 10:48:24 +03:00
if ( get_dosmode ) {
2023-06-22 16:12:25 +03:00
SMB_ASSERT ( smb_fname ! = NULL ) ;
2023-05-23 10:48:24 +03:00
* _mode = fdos_mode ( smb_fname - > fsp ) ;
2023-06-22 16:12:25 +03:00
if ( smb_fname - > fsp ! = NULL ) {
smb_fname - > st = smb_fname - > fsp - > fsp_name - > st ;
}
2023-05-23 10:48:24 +03:00
}
return true ;
}
static bool get_dir_entry ( TALLOC_CTX * ctx ,
connection_struct * conn ,
struct dptr_struct * dirptr ,
const char * mask ,
uint32_t dirtype ,
char * * _fname ,
off_t * _size ,
uint32_t * _mode ,
struct timespec * _date ,
bool check_descend ,
bool ask_sharemode )
{
char * fname = NULL ;
struct smb_filename * smb_fname = NULL ;
uint32_t mode = 0 ;
bool ok ;
ok = smbd_dirptr_get_entry ( ctx ,
dirptr ,
mask ,
dirtype ,
check_descend ,
ask_sharemode ,
true ,
smbd_dirptr_8_3_match_fn ,
smbd_dirptr_8_3_mode_fn ,
conn ,
& fname ,
& smb_fname ,
2023-06-09 16:05:07 +03:00
& mode ) ;
2023-05-23 10:48:24 +03:00
if ( ! ok ) {
return false ;
}
* _fname = talloc_move ( ctx , & fname ) ;
* _size = smb_fname - > st . st_ex_size ;
* _mode = mode ;
* _date = smb_fname - > st . st_ex_mtime ;
TALLOC_FREE ( smb_fname ) ;
return true ;
}
1996-05-04 11:50:46 +04:00
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a search .
Can be called from SMBsearch , SMBffirst or SMBfunique .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2008-01-05 02:37:24 +03:00
void reply_search ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
2009-06-19 02:07:14 +04:00
char * path = NULL ;
2015-10-28 20:08:28 +03:00
char * mask = NULL ;
2007-09-08 00:57:01 +04:00
char * directory = NULL ;
2009-07-21 22:35:17 +04:00
struct smb_filename * smb_fname = NULL ;
2007-09-13 01:48:20 +04:00
char * fname = NULL ;
2012-04-05 08:53:08 +04:00
off_t size ;
2015-04-27 02:02:55 +03:00
uint32_t mode ;
2009-05-14 17:34:42 +04:00
struct timespec date ;
2015-04-27 02:02:55 +03:00
uint32_t dirtype ;
2003-10-30 00:28:00 +03:00
unsigned int numentries = 0 ;
unsigned int maxentries = 0 ;
2007-10-19 04:40:25 +04:00
bool finished = False ;
2008-11-01 19:35:48 +03:00
const char * p ;
2002-12-04 02:57:45 +03:00
int status_len ;
char status [ 21 ] ;
int dptr_num = - 1 ;
2007-10-19 04:40:25 +04:00
bool check_descend = False ;
bool expect_close = False ;
2003-10-09 03:21:36 +04:00
NTSTATUS nt_status ;
2007-10-19 04:40:25 +04:00
bool mask_contains_wcard = False ;
bool allow_long_path_components = ( req - > flags2 & FLAGS2_LONG_PATH_COMPONENTS ) ? True : False ;
2007-09-11 22:31:29 +04:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
2014-06-11 17:12:32 +04:00
struct smbXsrv_connection * xconn = req - > xconn ;
2014-06-11 17:12:32 +04:00
struct smbd_server_connection * sconn = req - > sconn ;
2019-07-17 20:38:45 +03:00
files_struct * fsp = NULL ;
2019-10-31 19:51:06 +03:00
const struct loadparm_substitution * lp_sub =
loadparm_s3_global_substitution ( ) ;
2005-03-29 04:36:30 +04:00
2006-05-05 11:15:45 +04:00
START_PROFILE ( SMBsearch ) ;
2007-08-15 01:32:52 +04:00
if ( req - > wct < 2 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
2009-07-21 22:35:17 +04:00
goto out ;
2007-08-15 01:32:52 +04:00
}
2015-12-23 00:41:45 +03:00
if ( req - > posix_pathnames ) {
2008-11-03 00:33:20 +03:00
reply_unknown_new ( req , req - > cmd ) ;
2009-07-21 22:35:17 +04:00
goto out ;
2005-06-23 01:20:41 +04:00
}
2002-12-04 02:57:45 +03:00
/* If we were called as SMBffirst then we must expect close. */
2008-11-03 00:33:20 +03:00
if ( req - > cmd = = SMBffirst ) {
2002-12-04 02:57:45 +03:00
expect_close = True ;
2007-01-17 00:04:30 +03:00
}
2007-08-15 01:32:52 +04:00
2022-04-05 05:53:20 +03:00
reply_smb1_outbuf ( req , 1 , 3 ) ;
2008-11-02 14:20:47 +03:00
maxentries = SVAL ( req - > vwv + 0 , 0 ) ;
dirtype = SVAL ( req - > vwv + 1 , 0 ) ;
2008-11-01 19:35:48 +03:00
p = ( const char * ) req - > buf + 1 ;
2020-09-29 22:07:39 +03:00
p + = srvstr_get_path_req ( ctx , req , & path , p , STR_TERMINATE ,
& nt_status ) ;
2003-10-09 03:21:36 +04:00
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
2007-08-15 01:32:52 +04:00
reply_nterror ( req , nt_status ) ;
2009-07-21 22:35:17 +04:00
goto out ;
2003-10-09 03:21:36 +04:00
}
2005-03-16 02:17:03 +03:00
2019-07-03 22:13:59 +03:00
if ( smbreq_bufrem ( req , p ) < 3 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
goto out ;
}
2002-12-04 02:57:45 +03:00
p + + ;
status_len = SVAL ( p , 0 ) ;
p + = 2 ;
2007-09-11 22:31:29 +04:00
2011-04-29 05:57:02 +04:00
/* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
2002-12-04 02:57:45 +03:00
if ( status_len = = 0 ) {
2021-12-03 22:22:03 +03:00
const char * dirpath ;
2022-08-03 19:58:54 +03:00
struct files_struct * dirfsp = NULL ;
2016-02-27 03:35:17 +03:00
struct smb_filename * smb_dname = NULL ;
2021-12-03 22:22:03 +03:00
uint32_t ucf_flags = ucf_flags_from_smb_request ( req ) ;
2023-03-30 17:43:58 +03:00
nt_status = smb1_strip_dfs_path ( ctx , & ucf_flags , & path ) ;
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
reply_nterror ( req , nt_status ) ;
goto out ;
}
2021-12-03 22:22:03 +03:00
nt_status = filename_convert_smb1_search_path ( ctx ,
conn ,
path ,
ucf_flags ,
2022-08-03 19:58:54 +03:00
& dirfsp ,
2021-12-03 22:22:03 +03:00
& smb_dname ,
& mask ) ;
2009-06-19 02:07:14 +04:00
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
if ( NT_STATUS_EQUAL ( nt_status , NT_STATUS_PATH_NOT_COVERED ) ) {
reply_botherror ( req , NT_STATUS_PATH_NOT_COVERED ,
ERRSRV , ERRbadpath ) ;
2009-07-21 22:35:17 +04:00
goto out ;
2009-06-19 02:07:14 +04:00
}
reply_nterror ( req , nt_status ) ;
2009-07-21 22:35:17 +04:00
goto out ;
2009-06-19 02:07:14 +04:00
}
2002-12-04 02:57:45 +03:00
memset ( ( char * ) status , ' \0 ' , 21 ) ;
SCVAL ( status , 0 , ( dirtype & 0x1F ) ) ;
2007-09-08 00:57:01 +04:00
2019-07-16 03:13:33 +03:00
/*
* Open an fsp on this directory for the dptr .
*/
nt_status = SMB_VFS_CREATE_FILE (
conn , /* conn */
req , /* req */
2022-08-03 19:58:54 +03:00
dirfsp , /* dirfsp */
2019-07-16 03:13:33 +03:00
smb_dname , /* dname */
FILE_LIST_DIRECTORY , /* access_mask */
FILE_SHARE_READ |
FILE_SHARE_WRITE , /* share_access */
FILE_OPEN , /* create_disposition*/
FILE_DIRECTORY_FILE , /* create_options */
FILE_ATTRIBUTE_DIRECTORY , /* file_attributes */
NO_OPLOCK , /* oplock_request */
NULL , /* lease */
0 , /* allocation_size */
0 , /* private_flags */
NULL , /* sd */
NULL , /* ea_list */
& fsp , /* result */
NULL , /* pinfo */
NULL , /* in_context */
NULL ) ; /* out_context */
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
DBG_ERR ( " failed to open directory %s \n " ,
smb_fname_str_dbg ( smb_dname ) ) ;
reply_nterror ( req , nt_status ) ;
goto out ;
}
2007-09-08 00:57:01 +04:00
nt_status = dptr_create ( conn ,
2012-03-01 04:05:50 +04:00
NULL , /* req */
2019-07-16 03:13:33 +03:00
fsp , /* fsp */
2007-09-08 00:57:01 +04:00
True ,
mask ,
dirtype ,
2019-07-16 03:13:33 +03:00
& fsp - > dptr ) ;
2016-02-27 03:35:17 +03:00
TALLOC_FREE ( smb_dname ) ;
2007-09-08 00:57:01 +04:00
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
2019-07-16 03:13:33 +03:00
/*
* Use NULL here for the first parameter ( req )
* as this is not a client visible handle so
2023-06-07 18:18:28 +03:00
* can ' t be part of an SMB1 chain .
2019-07-16 03:13:33 +03:00
*/
2022-02-01 19:47:29 +03:00
close_file_free ( NULL , & fsp , NORMAL_CLOSE ) ;
2007-09-08 00:57:01 +04:00
reply_nterror ( req , nt_status ) ;
2009-07-21 22:35:17 +04:00
goto out ;
2007-09-08 00:57:01 +04:00
}
2019-07-16 03:13:33 +03:00
dptr_num = dptr_dnum ( fsp - > dptr ) ;
2021-12-03 22:22:03 +03:00
dirpath = dptr_path ( sconn , dptr_num ) ;
directory = talloc_strdup ( ctx , dirpath ) ;
if ( ! directory ) {
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
goto out ;
}
2019-07-16 03:13:33 +03:00
2002-12-04 02:57:45 +03:00
} else {
int status_dirtype ;
2009-08-07 11:31:45 +04:00
const char * dirpath ;
2023-06-08 13:37:43 +03:00
unsigned int dptr_filenum ;
uint32_t resume_key_index ;
2002-12-04 02:57:45 +03:00
2019-07-03 22:13:59 +03:00
if ( smbreq_bufrem ( req , p ) < 21 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
goto out ;
}
2002-12-04 02:57:45 +03:00
memcpy ( status , p , 21 ) ;
status_dirtype = CVAL ( status , 0 ) & 0x1F ;
2007-01-17 00:04:30 +03:00
if ( status_dirtype ! = ( dirtype & 0x1F ) ) {
2002-12-04 02:57:45 +03:00
dirtype = status_dirtype ;
2007-01-17 00:04:30 +03:00
}
2002-12-04 02:57:45 +03:00
2023-06-08 13:37:43 +03:00
dptr_num = CVAL ( status , 12 ) ;
fsp = dptr_fetch_lanman2_fsp ( sconn , dptr_num ) ;
2019-07-17 23:11:57 +03:00
if ( fsp = = NULL ) {
2002-12-04 02:57:45 +03:00
goto SearchEmpty ;
2007-01-17 00:04:30 +03:00
}
2023-06-08 13:37:43 +03:00
resume_key_index = PULL_LE_U32 ( status , 13 ) ;
dptr_filenum = dptr_FileNumber ( fsp - > dptr ) ;
if ( resume_key_index > dptr_filenum ) {
/*
* Haven ' t seen this resume key yet . Just stop
* the search .
*/
goto SearchEmpty ;
}
if ( resume_key_index < dptr_filenum ) {
/*
* The resume key was not the last one we
* sent , rewind and skip to what the client
* sent .
*/
dptr_RewindDir ( fsp - > dptr ) ;
dptr_filenum = dptr_FileNumber ( fsp - > dptr ) ;
SMB_ASSERT ( dptr_filenum = = 0 ) ;
while ( dptr_filenum < resume_key_index ) {
bool ok = get_dir_entry (
ctx ,
2023-05-23 10:48:24 +03:00
conn ,
2023-06-08 13:37:43 +03:00
fsp - > dptr ,
dptr_wcard ( sconn , dptr_num ) ,
dirtype ,
& fname ,
& size ,
& mode ,
& date ,
check_descend ,
false ) ;
TALLOC_FREE ( fname ) ;
if ( ! ok ) {
goto SearchEmpty ;
}
dptr_filenum = dptr_FileNumber ( fsp - > dptr ) ;
}
}
2009-08-06 14:15:51 +04:00
dirpath = dptr_path ( sconn , dptr_num ) ;
2009-08-07 11:31:45 +04:00
directory = talloc_strdup ( ctx , dirpath ) ;
if ( ! directory ) {
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
goto out ;
}
2015-10-28 20:08:28 +03:00
mask = talloc_strdup ( ctx , dptr_wcard ( sconn , dptr_num ) ) ;
2007-09-13 01:48:20 +04:00
if ( ! mask ) {
goto SearchEmpty ;
}
2009-08-06 14:15:51 +04:00
dirtype = dptr_attr ( sconn , dptr_num ) ;
2007-01-17 00:04:30 +03:00
}
2020-09-29 22:05:53 +03:00
mask_contains_wcard = dptr_has_wild ( fsp - > dptr ) ;
2007-01-17 00:04:30 +03:00
DEBUG ( 4 , ( " dptr_num is %d \n " , dptr_num ) ) ;
2011-04-29 05:52:48 +04:00
if ( ( dirtype & 0x1F ) = = FILE_ATTRIBUTE_VOLUME ) {
2007-08-15 01:32:52 +04:00
char buf [ DIR_STRUCT_SIZE ] ;
memcpy ( buf , status , 21 ) ;
2023-06-07 16:16:44 +03:00
make_dir_struct ( ctx ,
buf ,
" ??????????? " ,
volume_label ( ctx , SNUM ( conn ) ) ,
0 ,
FILE_ATTRIBUTE_VOLUME ,
0 ,
! allow_long_path_components ) ;
2023-06-08 13:37:43 +03:00
SCVAL ( buf , 12 , dptr_num ) ;
numentries = 1 ;
2007-08-15 01:32:52 +04:00
if ( message_push_blob ( & req - > outbuf ,
data_blob_const ( buf , sizeof ( buf ) ) )
= = - 1 ) {
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
2009-07-21 22:35:17 +04:00
goto out ;
2007-08-15 01:32:52 +04:00
}
2007-01-17 00:04:30 +03:00
} else {
unsigned int i ;
2014-03-05 17:00:40 +04:00
size_t hdr_size = ( ( uint8_t * ) smb_buf ( req - > outbuf ) + 3 - req - > outbuf ) ;
2014-05-21 12:56:26 +04:00
size_t available_space = xconn - > smb1 . sessions . max_send - hdr_size ;
2022-05-11 19:13:13 +03:00
bool ask_sharemode ;
2014-03-05 17:00:40 +04:00
maxentries = MIN ( maxentries , available_space / DIR_STRUCT_SIZE ) ;
2002-12-04 02:57:45 +03:00
2007-01-17 00:04:30 +03:00
DEBUG ( 8 , ( " dirpath=<%s> dontdescend=<%s> \n " ,
2019-10-31 19:51:06 +03:00
directory , lp_dont_descend ( ctx , lp_sub , SNUM ( conn ) ) ) ) ;
if ( in_list ( directory , lp_dont_descend ( ctx , lp_sub , SNUM ( conn ) ) , True ) ) {
2007-01-17 00:04:30 +03:00
check_descend = True ;
}
2002-12-04 02:57:45 +03:00
2022-05-11 19:13:13 +03:00
ask_sharemode = fsp_search_ask_sharemode ( fsp ) ;
2007-01-17 00:04:30 +03:00
for ( i = numentries ; ( i < maxentries ) & & ! finished ; i + + ) {
2008-04-07 11:21:19 +04:00
finished = ! get_dir_entry ( ctx ,
2023-05-23 10:48:24 +03:00
conn ,
2019-07-17 23:11:57 +03:00
fsp - > dptr ,
2008-04-07 11:21:19 +04:00
mask ,
dirtype ,
& fname ,
& size ,
& mode ,
& date ,
check_descend ,
ask_sharemode ) ;
2007-01-17 00:04:30 +03:00
if ( ! finished ) {
2007-08-15 01:32:52 +04:00
char buf [ DIR_STRUCT_SIZE ] ;
memcpy ( buf , status , 21 ) ;
2023-06-07 16:16:44 +03:00
make_dir_struct (
ctx ,
buf ,
mask ,
fname ,
size ,
mode ,
convert_timespec_to_time_t ( date ) ,
! allow_long_path_components ) ;
2023-06-08 13:37:43 +03:00
SCVAL ( buf , 12 , dptr_num ) ;
PUSH_LE_U32 ( buf ,
13 ,
dptr_FileNumber ( fsp - > dptr ) ) ;
2007-08-15 01:32:52 +04:00
if ( message_push_blob ( & req - > outbuf ,
data_blob_const ( buf , sizeof ( buf ) ) )
= = - 1 ) {
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
2009-07-21 22:35:17 +04:00
goto out ;
2007-08-15 01:32:52 +04:00
}
2007-01-17 00:04:30 +03:00
numentries + + ;
2002-12-04 02:57:45 +03:00
}
2023-06-08 13:20:31 +03:00
TALLOC_FREE ( fname ) ;
2007-01-17 00:04:30 +03:00
}
2002-12-04 02:57:45 +03:00
}
1996-05-04 11:50:46 +04:00
1999-12-13 16:27:58 +03:00
SearchEmpty :
1996-05-04 11:50:46 +04:00
2002-12-04 02:57:45 +03:00
/* If we were called as SMBffirst with smb_search_id == NULL
2019-07-17 23:11:57 +03:00
and no entries were found then return error and close fsp - > dptr
2002-12-04 02:57:45 +03:00
( X / Open spec ) */
2007-01-17 00:04:30 +03:00
if ( numentries = = 0 ) {
2019-07-17 23:35:57 +03:00
dptr_num = - 1 ;
2019-07-17 20:38:45 +03:00
if ( fsp ! = NULL ) {
2022-02-01 19:47:29 +03:00
close_file_free ( NULL , & fsp , NORMAL_CLOSE ) ;
2019-07-17 20:38:45 +03:00
}
2007-01-17 00:04:30 +03:00
} else if ( expect_close & & status_len = = 0 ) {
2005-01-29 02:17:12 +03:00
/* Close the dptr - we know it's gone */
2019-07-17 23:35:57 +03:00
dptr_num = - 1 ;
2019-07-17 20:38:45 +03:00
if ( fsp ! = NULL ) {
2022-02-01 19:47:29 +03:00
close_file_free ( NULL , & fsp , NORMAL_CLOSE ) ;
2019-07-17 20:38:45 +03:00
}
2002-12-04 02:57:45 +03:00
}
2019-07-17 23:11:57 +03:00
/* If we were called as SMBfunique, then we can close the fsp->dptr now ! */
2008-11-03 00:33:20 +03:00
if ( dptr_num > = 0 & & req - > cmd = = SMBfunique ) {
2019-07-17 23:35:57 +03:00
dptr_num = - 1 ;
2019-07-17 23:11:57 +03:00
/* fsp may have been closed above. */
2019-07-17 20:38:45 +03:00
if ( fsp ! = NULL ) {
2022-02-01 19:47:29 +03:00
close_file_free ( NULL , & fsp , NORMAL_CLOSE ) ;
2019-07-17 20:38:45 +03:00
}
2005-01-29 02:17:12 +03:00
}
2005-10-31 23:11:58 +03:00
if ( ( numentries = = 0 ) & & ! mask_contains_wcard ) {
2007-08-15 01:32:52 +04:00
reply_botherror ( req , STATUS_NO_MORE_FILES , ERRDOS , ERRnofiles ) ;
2009-07-21 22:35:17 +04:00
goto out ;
2005-01-29 02:17:12 +03:00
}
2002-12-04 02:57:45 +03:00
2007-08-15 01:32:52 +04:00
SSVAL ( req - > outbuf , smb_vwv0 , numentries ) ;
SSVAL ( req - > outbuf , smb_vwv1 , 3 + numentries * DIR_STRUCT_SIZE ) ;
SCVAL ( smb_buf ( req - > outbuf ) , 0 , 5 ) ;
SSVAL ( smb_buf ( req - > outbuf ) , 1 , numentries * DIR_STRUCT_SIZE ) ;
2002-12-04 02:57:45 +03:00
2005-03-29 04:36:30 +04:00
/* The replies here are never long name. */
2007-08-15 01:32:52 +04:00
SSVAL ( req - > outbuf , smb_flg2 ,
SVAL ( req - > outbuf , smb_flg2 ) & ( ~ FLAGS2_IS_LONG_NAME ) ) ;
2005-03-29 04:36:30 +04:00
if ( ! allow_long_path_components ) {
2007-08-15 01:32:52 +04:00
SSVAL ( req - > outbuf , smb_flg2 ,
SVAL ( req - > outbuf , smb_flg2 )
& ( ~ FLAGS2_LONG_PATH_COMPONENTS ) ) ;
2005-03-29 04:36:30 +04:00
}
2005-03-25 22:52:01 +03:00
/* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
2007-08-15 01:32:52 +04:00
SSVAL ( req - > outbuf , smb_flg2 ,
( SVAL ( req - > outbuf , smb_flg2 ) & ( ~ FLAGS2_UNICODE_STRINGS ) ) ) ;
2002-12-04 02:57:45 +03:00
2007-09-08 00:57:01 +04:00
DEBUG ( 4 , ( " %s mask=%s path=%s dtype=%d nument=%u of %u \n " ,
2008-11-03 00:33:20 +03:00
smb_fn_name ( req - > cmd ) ,
2007-09-08 00:57:01 +04:00
mask ,
2009-08-07 11:31:45 +04:00
directory ,
2007-09-08 00:57:01 +04:00
dirtype ,
numentries ,
maxentries ) ) ;
2009-07-21 22:35:17 +04:00
out :
2009-08-07 11:31:45 +04:00
TALLOC_FREE ( directory ) ;
2015-10-28 20:08:28 +03:00
TALLOC_FREE ( mask ) ;
2009-07-21 22:35:17 +04:00
TALLOC_FREE ( smb_fname ) ;
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBsearch ) ;
2007-08-15 01:32:52 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a fclose ( stop directory search ) .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2008-01-05 02:37:24 +03:00
void reply_fclose ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2002-12-04 02:57:45 +03:00
int status_len ;
int dptr_num = - 2 ;
2008-11-01 19:35:48 +03:00
const char * p ;
2007-09-12 03:57:59 +04:00
char * path = NULL ;
2003-10-09 03:21:36 +04:00
NTSTATUS err ;
2007-09-12 03:57:59 +04:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
2010-06-12 13:41:40 +04:00
struct smbd_server_connection * sconn = req - > sconn ;
2019-07-17 20:40:51 +03:00
files_struct * fsp = NULL ;
2001-03-10 14:57:38 +03:00
2006-05-05 11:15:45 +04:00
START_PROFILE ( SMBfclose ) ;
2015-12-23 00:41:45 +03:00
if ( req - > posix_pathnames ) {
2008-11-03 00:33:20 +03:00
reply_unknown_new ( req , req - > cmd ) ;
2006-05-05 11:15:45 +04:00
END_PROFILE ( SMBfclose ) ;
2007-08-15 01:32:52 +04:00
return ;
2005-06-23 01:20:41 +04:00
}
2008-11-01 19:35:48 +03:00
p = ( const char * ) req - > buf + 1 ;
2020-09-29 22:14:11 +03:00
p + = srvstr_get_path_req ( ctx , req , & path , p , STR_TERMINATE ,
& err ) ;
2003-10-09 03:21:36 +04:00
if ( ! NT_STATUS_IS_OK ( err ) ) {
2007-08-15 01:32:52 +04:00
reply_nterror ( req , err ) ;
2003-10-09 03:21:36 +04:00
END_PROFILE ( SMBfclose ) ;
2007-08-15 01:32:52 +04:00
return ;
2003-10-09 03:21:36 +04:00
}
2019-07-03 22:15:56 +03:00
if ( smbreq_bufrem ( req , p ) < 3 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBfclose ) ;
return ;
}
2002-12-04 02:57:45 +03:00
p + + ;
status_len = SVAL ( p , 0 ) ;
p + = 2 ;
1996-05-04 11:50:46 +04:00
2002-12-04 02:57:45 +03:00
if ( status_len = = 0 ) {
2009-12-21 22:16:38 +03:00
reply_force_doserror ( req , ERRSRV , ERRsrverror ) ;
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBfclose ) ;
2007-08-15 01:32:52 +04:00
return ;
2002-12-04 02:57:45 +03:00
}
1996-05-04 11:50:46 +04:00
2019-07-03 22:15:56 +03:00
if ( smbreq_bufrem ( req , p ) < 21 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBfclose ) ;
return ;
}
2023-06-08 13:37:43 +03:00
dptr_num = CVAL ( p , 12 ) ;
1996-05-04 11:50:46 +04:00
2023-06-08 13:37:43 +03:00
fsp = dptr_fetch_lanman2_fsp ( sconn , dptr_num ) ;
2019-07-17 23:07:33 +03:00
if ( fsp ! = NULL ) {
2019-07-17 23:37:02 +03:00
/* Close the file - we know it's gone */
2022-02-01 19:47:29 +03:00
close_file_free ( NULL , & fsp , NORMAL_CLOSE ) ;
2019-07-17 23:37:02 +03:00
dptr_num = - 1 ;
2002-12-04 02:57:45 +03:00
}
1996-05-04 11:50:46 +04:00
2022-04-05 05:53:20 +03:00
reply_smb1_outbuf ( req , 1 , 0 ) ;
2007-08-15 01:32:52 +04:00
SSVAL ( req - > outbuf , smb_vwv0 , 0 ) ;
1996-05-04 11:50:46 +04:00
2002-12-04 02:57:45 +03:00
DEBUG ( 3 , ( " search close \n " ) ) ;
1996-05-04 11:50:46 +04:00
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBfclose ) ;
2007-08-15 01:32:52 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to an open .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-10-23 04:58:28 +04:00
2008-01-05 02:37:24 +03:00
void reply_open ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
2009-06-05 05:39:55 +04:00
struct smb_filename * smb_fname = NULL ;
2007-09-08 00:57:01 +04:00
char * fname = NULL ;
2015-04-27 02:02:55 +03:00
uint32_t fattr = 0 ;
2012-04-05 08:53:08 +04:00
off_t size = 0 ;
2002-12-04 02:57:45 +03:00
time_t mtime = 0 ;
2005-07-08 08:51:27 +04:00
int info ;
2022-07-27 22:05:17 +03:00
struct files_struct * dirfsp = NULL ;
2002-12-04 02:57:45 +03:00
files_struct * fsp ;
2007-08-14 17:57:36 +04:00
int oplock_request ;
2005-07-08 08:51:27 +04:00
int deny_mode ;
2015-04-27 02:02:55 +03:00
uint32_t dos_attr ;
uint32_t access_mask ;
uint32_t share_mode ;
uint32_t create_disposition ;
uint32_t create_options = 0 ;
2010-03-06 02:10:30 +03:00
uint32_t private_flags = 0 ;
2003-10-09 03:21:36 +04:00
NTSTATUS status ;
2016-10-13 13:42:59 +03:00
uint32_t ucf_flags ;
2022-07-27 22:05:17 +03:00
NTTIME twrp = 0 ;
2007-09-11 22:31:29 +04:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
2007-07-05 20:26:27 +04:00
2002-12-04 02:57:45 +03:00
START_PROFILE ( SMBopen ) ;
2007-07-05 20:26:27 +04:00
2007-08-14 18:31:55 +04:00
if ( req - > wct < 2 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
2009-06-05 05:39:55 +04:00
goto out ;
2007-08-14 17:57:36 +04:00
}
2007-09-11 22:31:29 +04:00
2007-08-14 18:31:55 +04:00
oplock_request = CORE_OPLOCK_REQUEST ( req - > inbuf ) ;
2008-11-02 14:20:47 +03:00
deny_mode = SVAL ( req - > vwv + 0 , 0 ) ;
dos_attr = SVAL ( req - > vwv + 1 , 0 ) ;
1996-05-04 11:50:46 +04:00
2008-11-02 02:59:03 +03:00
srvstr_get_path_req ( ctx , req , & fname , ( const char * ) req - > buf + 1 ,
STR_TERMINATE , & status ) ;
2003-10-09 03:21:36 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-14 18:31:55 +04:00
reply_nterror ( req , status ) ;
2009-06-05 05:39:55 +04:00
goto out ;
2003-10-09 03:21:36 +04:00
}
2000-03-09 01:14:30 +03:00
2013-07-09 22:02:39 +04:00
if ( ! map_open_params_to_ntcreate ( fname , deny_mode ,
OPENX_FILE_EXISTS_OPEN , & access_mask ,
& share_mode , & create_disposition ,
& create_options , & private_flags ) ) {
reply_force_doserror ( req , ERRDOS , ERRbadaccess ) ;
goto out ;
}
2016-10-13 13:42:59 +03:00
ucf_flags = filename_create_ucf_flags ( req , create_disposition ) ;
2022-07-27 22:05:17 +03:00
if ( ucf_flags & UCF_GMT_PATHNAME ) {
2022-08-04 20:02:15 +03:00
extract_snapshot_token ( fname , & twrp ) ;
2022-07-27 22:05:17 +03:00
}
2023-03-30 17:02:08 +03:00
status = smb1_strip_dfs_path ( ctx , & ucf_flags , & fname ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
reply_nterror ( req , status ) ;
goto out ;
}
2022-07-27 22:05:17 +03:00
status = filename_convert_dirfsp ( ctx ,
conn ,
fname ,
ucf_flags ,
twrp ,
& dirfsp ,
& smb_fname ) ;
2009-06-17 04:23:54 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
if ( NT_STATUS_EQUAL ( status , NT_STATUS_PATH_NOT_COVERED ) ) {
reply_botherror ( req ,
NT_STATUS_PATH_NOT_COVERED ,
ERRSRV , ERRbadpath ) ;
goto out ;
}
reply_nterror ( req , status ) ;
goto out ;
2005-07-08 08:51:27 +04:00
}
2008-10-21 04:43:45 +04:00
status = SMB_VFS_CREATE_FILE (
conn , /* conn */
req , /* req */
2022-07-27 22:05:17 +03:00
dirfsp , /* dirfsp */
2009-06-12 23:54:11 +04:00
smb_fname , /* fname */
2008-10-21 04:43:45 +04:00
access_mask , /* access_mask */
share_mode , /* share_access */
create_disposition , /* create_disposition*/
create_options , /* create_options */
dos_attr , /* file_attributes */
oplock_request , /* oplock_request */
2013-08-21 17:56:14 +04:00
NULL , /* lease */
2008-10-21 04:43:45 +04:00
0 , /* allocation_size */
2010-03-06 02:10:30 +03:00
private_flags ,
2008-10-21 04:43:45 +04:00
NULL , /* sd */
NULL , /* ea_list */
& fsp , /* result */
2014-11-26 16:12:51 +03:00
& info , /* pinfo */
NULL , NULL ) ; /* create context */
2002-12-04 02:57:45 +03:00
2006-07-11 22:01:26 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2014-09-16 08:55:39 +04:00
if ( open_was_deferred ( req - > xconn , req - > mid ) ) {
2004-06-08 20:14:31 +04:00
/* We have re-scheduled this call. */
2009-06-05 05:39:55 +04:00
goto out ;
2007-08-16 04:37:07 +04:00
}
2019-07-05 10:52:43 +03:00
if ( ! NT_STATUS_EQUAL ( status , NT_STATUS_SHARING_VIOLATION ) ) {
reply_openerror ( req , status ) ;
goto out ;
}
fsp = fcb_or_dos_open (
req ,
smb_fname ,
access_mask ,
create_options ,
private_flags ) ;
if ( fsp = = NULL ) {
2019-07-30 15:54:40 +03:00
bool ok = defer_smb1_sharing_violation ( req ) ;
if ( ok ) {
goto out ;
}
2019-07-05 10:52:43 +03:00
reply_openerror ( req , status ) ;
goto out ;
}
2002-12-04 02:57:45 +03:00
}
2013-11-22 20:17:44 +04:00
/* Ensure we're pointing at the correct stat struct. */
TALLOC_FREE ( smb_fname ) ;
smb_fname = fsp - > fsp_name ;
2009-06-05 05:39:55 +04:00
size = smb_fname - > st . st_ex_size ;
2020-10-19 21:41:43 +03:00
fattr = fdos_mode ( fsp ) ;
2009-07-09 04:51:35 +04:00
2009-06-05 05:39:55 +04:00
mtime = convert_timespec_to_time_t ( smb_fname - > st . st_ex_mtime ) ;
2002-12-04 02:57:45 +03:00
2011-04-29 05:57:02 +04:00
if ( fattr & FILE_ATTRIBUTE_DIRECTORY ) {
2009-07-11 01:50:37 +04:00
DEBUG ( 3 , ( " attempt to open a directory %s \n " ,
fsp_str_dbg ( fsp ) ) ) ;
2022-02-01 19:47:29 +03:00
close_file_free ( req , & fsp , ERROR_CLOSE ) ;
2009-12-21 22:05:25 +03:00
reply_botherror ( req , NT_STATUS_ACCESS_DENIED ,
ERRDOS , ERRnoaccess ) ;
2009-06-05 05:39:55 +04:00
goto out ;
2002-12-04 02:57:45 +03:00
}
2007-08-14 18:31:55 +04:00
2022-04-05 05:53:20 +03:00
reply_smb1_outbuf ( req , 7 , 0 ) ;
2007-08-14 18:31:55 +04:00
SSVAL ( req - > outbuf , smb_vwv0 , fsp - > fnum ) ;
SSVAL ( req - > outbuf , smb_vwv1 , fattr ) ;
2005-07-08 08:51:27 +04:00
if ( lp_dos_filetime_resolution ( SNUM ( conn ) ) ) {
2007-08-14 18:31:55 +04:00
srv_put_dos_date3 ( ( char * ) req - > outbuf , smb_vwv2 , mtime & ~ 1 ) ;
2005-07-08 08:51:27 +04:00
} else {
2007-08-14 18:31:55 +04:00
srv_put_dos_date3 ( ( char * ) req - > outbuf , smb_vwv2 , mtime ) ;
2005-07-08 08:51:27 +04:00
}
2015-05-03 07:01:14 +03:00
SIVAL ( req - > outbuf , smb_vwv4 , ( uint32_t ) size ) ;
2007-08-14 18:31:55 +04:00
SSVAL ( req - > outbuf , smb_vwv6 , deny_mode ) ;
2002-12-04 02:57:45 +03:00
2005-07-08 08:51:27 +04:00
if ( oplock_request & & lp_fake_oplocks ( SNUM ( conn ) ) ) {
2007-08-14 18:31:55 +04:00
SCVAL ( req - > outbuf , smb_flg ,
CVAL ( req - > outbuf , smb_flg ) | CORE_OPLOCK_GRANTED ) ;
2005-07-08 08:51:27 +04:00
}
2008-10-19 17:30:12 +04:00
2005-07-08 08:51:27 +04:00
if ( EXCLUSIVE_OPLOCK_TYPE ( fsp - > oplock_type ) ) {
2007-08-14 18:31:55 +04:00
SCVAL ( req - > outbuf , smb_flg ,
CVAL ( req - > outbuf , smb_flg ) | CORE_OPLOCK_GRANTED ) ;
2005-07-08 08:51:27 +04:00
}
2009-06-05 05:39:55 +04:00
out :
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBopen ) ;
2007-08-14 18:31:55 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to an open and X .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2008-01-05 02:37:24 +03:00
void reply_open_and_X ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
2009-06-05 05:39:55 +04:00
struct smb_filename * smb_fname = NULL ;
2007-09-08 00:57:01 +04:00
char * fname = NULL ;
2015-04-27 02:02:55 +03:00
uint16_t open_flags ;
2007-07-23 13:54:36 +04:00
int deny_mode ;
2015-04-27 02:02:55 +03:00
uint32_t smb_attr ;
2002-12-04 02:57:45 +03:00
/* Breakout the oplock request bits so we can set the
reply bits separately . */
2007-07-23 13:54:36 +04:00
int ex_oplock_request ;
int core_oplock_request ;
int oplock_request ;
1996-05-04 11:50:46 +04:00
#if 0
2008-11-02 14:20:47 +03:00
int smb_sattr = SVAL ( req - > vwv + 4 , 0 ) ;
2015-04-27 02:02:55 +03:00
uint32_t smb_time = make_unix_date3 ( req - > vwv + 6 ) ;
1996-05-04 11:50:46 +04:00
# endif
2007-07-23 13:54:36 +04:00
int smb_ofun ;
2015-04-27 02:02:55 +03:00
uint32_t fattr = 0 ;
2005-07-08 08:51:27 +04:00
int mtime = 0 ;
2002-12-04 02:57:45 +03:00
int smb_action = 0 ;
2022-07-27 22:00:32 +03:00
struct files_struct * dirfsp = NULL ;
2002-12-04 02:57:45 +03:00
files_struct * fsp ;
2003-10-09 03:21:36 +04:00
NTSTATUS status ;
2008-10-14 03:59:36 +04:00
uint64_t allocation_size ;
2005-04-05 05:20:32 +04:00
ssize_t retval = - 1 ;
2015-04-27 02:02:55 +03:00
uint32_t access_mask ;
uint32_t share_mode ;
uint32_t create_disposition ;
uint32_t create_options = 0 ;
2010-03-06 02:10:30 +03:00
uint32_t private_flags = 0 ;
2016-10-13 13:42:59 +03:00
uint32_t ucf_flags ;
2022-07-27 22:00:32 +03:00
NTTIME twrp = 0 ;
2007-09-11 22:31:29 +04:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
2005-04-05 05:20:32 +04:00
2002-12-04 02:57:45 +03:00
START_PROFILE ( SMBopenX ) ;
2007-07-23 13:54:36 +04:00
if ( req - > wct < 15 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
2009-06-05 05:39:55 +04:00
goto out ;
2007-07-23 13:54:36 +04:00
}
2008-11-02 14:20:47 +03:00
open_flags = SVAL ( req - > vwv + 2 , 0 ) ;
deny_mode = SVAL ( req - > vwv + 3 , 0 ) ;
smb_attr = SVAL ( req - > vwv + 5 , 0 ) ;
2007-07-23 13:54:36 +04:00
ex_oplock_request = EXTENDED_OPLOCK_REQUEST ( req - > inbuf ) ;
core_oplock_request = CORE_OPLOCK_REQUEST ( req - > inbuf ) ;
oplock_request = ex_oplock_request | core_oplock_request ;
2008-11-02 14:20:47 +03:00
smb_ofun = SVAL ( req - > vwv + 8 , 0 ) ;
allocation_size = ( uint64_t ) IVAL ( req - > vwv + 9 , 0 ) ;
2007-07-05 20:26:27 +04:00
2002-12-04 02:57:45 +03:00
/* If it's an IPC, pass off the pipe handler. */
if ( IS_IPC ( conn ) ) {
if ( lp_nt_pipe_support ( ) ) {
2007-07-23 13:54:36 +04:00
reply_open_pipe_and_X ( conn , req ) ;
2002-12-04 02:57:45 +03:00
} else {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_NETWORK_ACCESS_DENIED ) ;
2002-12-04 02:57:45 +03:00
}
2009-06-05 05:39:55 +04:00
goto out ;
2002-12-04 02:57:45 +03:00
}
1996-08-15 19:11:34 +04:00
2002-12-04 02:57:45 +03:00
/* XXXX we need to handle passed times, sattr and flags */
2008-11-02 02:59:03 +03:00
srvstr_get_path_req ( ctx , req , & fname , ( const char * ) req - > buf ,
STR_TERMINATE , & status ) ;
2003-10-09 03:21:36 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-07-23 13:54:36 +04:00
reply_nterror ( req , status ) ;
2009-06-05 05:39:55 +04:00
goto out ;
2003-10-09 03:21:36 +04:00
}
2000-03-09 01:14:30 +03:00
2013-07-09 22:02:39 +04:00
if ( ! map_open_params_to_ntcreate ( fname , deny_mode ,
smb_ofun ,
& access_mask , & share_mode ,
& create_disposition ,
& create_options ,
& private_flags ) ) {
reply_force_doserror ( req , ERRDOS , ERRbadaccess ) ;
goto out ;
}
2016-10-13 13:42:59 +03:00
ucf_flags = filename_create_ucf_flags ( req , create_disposition ) ;
2022-07-27 22:00:32 +03:00
if ( ucf_flags & UCF_GMT_PATHNAME ) {
2022-08-04 20:02:15 +03:00
extract_snapshot_token ( fname , & twrp ) ;
2022-07-27 22:00:32 +03:00
}
2023-03-30 17:02:32 +03:00
status = smb1_strip_dfs_path ( ctx , & ucf_flags , & fname ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
reply_nterror ( req , status ) ;
goto out ;
}
2022-07-27 22:00:32 +03:00
status = filename_convert_dirfsp ( ctx ,
conn ,
fname ,
ucf_flags ,
twrp ,
& dirfsp ,
& smb_fname ) ;
2009-06-17 04:23:54 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
if ( NT_STATUS_EQUAL ( status , NT_STATUS_PATH_NOT_COVERED ) ) {
reply_botherror ( req ,
NT_STATUS_PATH_NOT_COVERED ,
ERRSRV , ERRbadpath ) ;
goto out ;
}
reply_nterror ( req , status ) ;
2009-06-05 05:39:55 +04:00
goto out ;
}
2008-10-21 04:43:45 +04:00
status = SMB_VFS_CREATE_FILE (
conn , /* conn */
req , /* req */
2022-07-27 22:00:32 +03:00
dirfsp , /* dirfsp */
2009-06-12 23:54:11 +04:00
smb_fname , /* fname */
2008-10-21 04:43:45 +04:00
access_mask , /* access_mask */
share_mode , /* share_access */
create_disposition , /* create_disposition*/
create_options , /* create_options */
smb_attr , /* file_attributes */
oplock_request , /* oplock_request */
2013-08-21 17:56:14 +04:00
NULL , /* lease */
2008-10-21 04:43:45 +04:00
0 , /* allocation_size */
2010-03-06 02:10:30 +03:00
private_flags ,
2008-10-21 04:43:45 +04:00
NULL , /* sd */
NULL , /* ea_list */
& fsp , /* result */
2014-11-26 16:12:51 +03:00
& smb_action , /* pinfo */
NULL , NULL ) ; /* create context */
2007-08-16 21:42:34 +04:00
2006-07-11 22:01:26 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2014-09-16 08:55:39 +04:00
if ( open_was_deferred ( req - > xconn , req - > mid ) ) {
2004-06-08 20:14:31 +04:00
/* We have re-scheduled this call. */
2009-06-05 05:39:55 +04:00
goto out ;
2007-08-15 17:44:34 +04:00
}
2019-07-05 10:52:43 +03:00
if ( ! NT_STATUS_EQUAL ( status , NT_STATUS_SHARING_VIOLATION ) ) {
reply_openerror ( req , status ) ;
goto out ;
}
fsp = fcb_or_dos_open (
req ,
smb_fname ,
access_mask ,
create_options ,
private_flags ) ;
if ( fsp = = NULL ) {
2019-07-30 15:54:40 +03:00
bool ok = defer_smb1_sharing_violation ( req ) ;
if ( ok ) {
goto out ;
}
2019-07-05 10:52:43 +03:00
reply_openerror ( req , status ) ;
goto out ;
}
2019-07-30 15:54:40 +03:00
2019-07-05 10:52:43 +03:00
smb_action = FILE_WAS_OPENED ;
2002-12-04 02:57:45 +03:00
}
2005-04-05 05:20:32 +04:00
/* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
if the file is truncated or created . */
if ( ( ( smb_action = = FILE_WAS_CREATED ) | | ( smb_action = = FILE_WAS_OVERWRITTEN ) ) & & allocation_size ) {
fsp - > initial_allocation_size = smb_roundup ( fsp - > conn , allocation_size ) ;
if ( vfs_allocate_file_space ( fsp , fsp - > initial_allocation_size ) = = - 1 ) {
2022-02-01 19:47:29 +03:00
close_file_free ( req , & fsp , ERROR_CLOSE ) ;
2007-07-23 13:54:36 +04:00
reply_nterror ( req , NT_STATUS_DISK_FULL ) ;
2009-06-05 05:39:55 +04:00
goto out ;
2005-04-05 05:20:32 +04:00
}
2012-04-05 08:53:08 +04:00
retval = vfs_set_filelen ( fsp , ( off_t ) allocation_size ) ;
2005-04-05 05:20:32 +04:00
if ( retval < 0 ) {
2022-02-01 19:47:29 +03:00
close_file_free ( req , & fsp , ERROR_CLOSE ) ;
2007-07-23 13:54:36 +04:00
reply_nterror ( req , NT_STATUS_DISK_FULL ) ;
2009-06-05 05:39:55 +04:00
goto out ;
2005-04-01 04:21:55 +04:00
}
2010-12-16 03:49:04 +03:00
status = vfs_stat_fsp ( fsp ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2022-02-01 19:47:29 +03:00
close_file_free ( req , & fsp , ERROR_CLOSE ) ;
2010-12-16 03:49:04 +03:00
reply_nterror ( req , status ) ;
goto out ;
}
2005-04-01 04:21:55 +04:00
}
2020-10-19 21:42:03 +03:00
fattr = fdos_mode ( fsp ) ;
2011-04-29 05:57:02 +04:00
if ( fattr & FILE_ATTRIBUTE_DIRECTORY ) {
2022-02-01 19:47:29 +03:00
close_file_free ( req , & fsp , ERROR_CLOSE ) ;
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_ACCESS_DENIED ) ;
2009-06-05 05:39:55 +04:00
goto out ;
2002-12-04 02:57:45 +03:00
}
2019-07-26 17:20:17 +03:00
mtime = convert_timespec_to_time_t ( fsp - > fsp_name - > st . st_ex_mtime ) ;
2002-12-04 02:57:45 +03:00
/* If the caller set the extended oplock request bit
and we granted one ( by whatever means ) - set the
correct bit for extended oplock reply .
*/
2005-07-08 08:51:27 +04:00
if ( ex_oplock_request & & lp_fake_oplocks ( SNUM ( conn ) ) ) {
2002-12-04 02:57:45 +03:00
smb_action | = EXTENDED_OPLOCK_GRANTED ;
2005-07-08 08:51:27 +04:00
}
2002-12-04 02:57:45 +03:00
2005-07-08 08:51:27 +04:00
if ( ex_oplock_request & & EXCLUSIVE_OPLOCK_TYPE ( fsp - > oplock_type ) ) {
2002-12-04 02:57:45 +03:00
smb_action | = EXTENDED_OPLOCK_GRANTED ;
2005-07-08 08:51:27 +04:00
}
2002-12-04 02:57:45 +03:00
/* If the caller set the core oplock request bit
and we granted one ( by whatever means ) - set the
correct bit for core oplock reply .
*/
2007-07-23 13:54:36 +04:00
if ( open_flags & EXTENDED_RESPONSE_REQUIRED ) {
2022-04-05 05:53:20 +03:00
reply_smb1_outbuf ( req , 19 , 0 ) ;
2007-07-23 13:54:36 +04:00
} else {
2022-04-05 05:53:20 +03:00
reply_smb1_outbuf ( req , 15 , 0 ) ;
2007-07-23 13:54:36 +04:00
}
2012-02-26 19:49:09 +04:00
SSVAL ( req - > outbuf , smb_vwv0 , 0xff ) ; /* andx chain ends */
SSVAL ( req - > outbuf , smb_vwv1 , 0 ) ; /* no andx offset */
2005-07-08 08:51:27 +04:00
if ( core_oplock_request & & lp_fake_oplocks ( SNUM ( conn ) ) ) {
2007-07-23 13:54:36 +04:00
SCVAL ( req - > outbuf , smb_flg ,
CVAL ( req - > outbuf , smb_flg ) | CORE_OPLOCK_GRANTED ) ;
2005-07-08 08:51:27 +04:00
}
2002-12-04 02:57:45 +03:00
2005-07-08 08:51:27 +04:00
if ( core_oplock_request & & EXCLUSIVE_OPLOCK_TYPE ( fsp - > oplock_type ) ) {
2007-07-23 13:54:36 +04:00
SCVAL ( req - > outbuf , smb_flg ,
CVAL ( req - > outbuf , smb_flg ) | CORE_OPLOCK_GRANTED ) ;
2005-07-08 08:51:27 +04:00
}
2002-12-04 02:57:45 +03:00
2007-07-23 13:54:36 +04:00
SSVAL ( req - > outbuf , smb_vwv2 , fsp - > fnum ) ;
SSVAL ( req - > outbuf , smb_vwv3 , fattr ) ;
2005-07-08 08:51:27 +04:00
if ( lp_dos_filetime_resolution ( SNUM ( conn ) ) ) {
2007-07-23 13:54:36 +04:00
srv_put_dos_date3 ( ( char * ) req - > outbuf , smb_vwv4 , mtime & ~ 1 ) ;
2005-07-08 08:51:27 +04:00
} else {
2007-07-23 13:54:36 +04:00
srv_put_dos_date3 ( ( char * ) req - > outbuf , smb_vwv4 , mtime ) ;
2005-07-08 08:51:27 +04:00
}
2015-05-03 07:01:14 +03:00
SIVAL ( req - > outbuf , smb_vwv6 , ( uint32_t ) fsp - > fsp_name - > st . st_ex_size ) ;
2007-07-23 13:54:36 +04:00
SSVAL ( req - > outbuf , smb_vwv8 , GET_OPENX_MODE ( deny_mode ) ) ;
SSVAL ( req - > outbuf , smb_vwv11 , smb_action ) ;
2002-12-04 02:57:45 +03:00
2005-07-08 08:51:27 +04:00
if ( open_flags & EXTENDED_RESPONSE_REQUIRED ) {
2010-06-03 12:36:05 +04:00
SIVAL ( req - > outbuf , smb_vwv15 , SEC_STD_ALL ) ;
2005-07-08 08:51:27 +04:00
}
2009-06-05 05:39:55 +04:00
out :
TALLOC_FREE ( smb_fname ) ;
END_PROFILE ( SMBopenX ) ;
2007-07-23 13:54:36 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a SMBulogoffX .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2020-03-12 20:19:31 +03:00
static struct tevent_req * reply_ulogoffX_send ( struct smb_request * smb1req ,
struct smbXsrv_session * session ) ;
static void reply_ulogoffX_done ( struct tevent_req * req ) ;
2020-03-12 20:15:10 +03:00
void reply_ulogoffX ( struct smb_request * smb1req )
1996-05-04 11:50:46 +04:00
{
2020-01-02 18:26:03 +03:00
struct timeval now = timeval_current ( ) ;
2012-04-01 23:19:53 +04:00
struct smbXsrv_session * session = NULL ;
2020-03-12 20:19:31 +03:00
struct tevent_req * req ;
2012-04-01 23:19:53 +04:00
NTSTATUS status ;
2007-07-30 23:53:57 +04:00
2020-03-12 20:19:31 +03:00
/*
* Don ' t setup the profile charge here , take
* it in reply_ulogoffX_done ( ) . Not strictly correct
* but better than the other SMB1 async
* code that double - charges at the moment .
*/
1996-05-04 11:50:46 +04:00
2020-03-12 20:15:10 +03:00
status = smb1srv_session_lookup ( smb1req - > xconn ,
smb1req - > vuid ,
2020-01-02 18:26:03 +03:00
timeval_to_nttime ( & now ) ,
& session ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2020-03-12 20:19:31 +03:00
/* Not going async, profile here. */
START_PROFILE ( SMBulogoffX ) ;
2020-03-12 20:16:42 +03:00
DBG_WARNING ( " ulogoff, vuser id %llu does not map to user. \n " ,
( unsigned long long ) smb1req - > vuid ) ;
2012-05-03 17:52:41 +04:00
2020-03-12 20:15:10 +03:00
smb1req - > vuid = UID_FIELD_INVALID ;
reply_force_doserror ( smb1req , ERRSRV , ERRbaduid ) ;
2012-05-03 17:52:41 +04:00
END_PROFILE ( SMBulogoffX ) ;
return ;
2007-07-30 23:53:57 +04:00
}
1996-05-04 11:50:46 +04:00
2020-03-12 20:19:31 +03:00
req = reply_ulogoffX_send ( smb1req , session ) ;
if ( req = = NULL ) {
/* Not going async, profile here. */
START_PROFILE ( SMBulogoffX ) ;
reply_force_doserror ( smb1req , ERRDOS , ERRnomem ) ;
2012-04-01 23:19:53 +04:00
END_PROFILE ( SMBulogoffX ) ;
return ;
2007-07-30 23:53:57 +04:00
}
1996-10-05 14:41:13 +04:00
2020-03-12 20:19:31 +03:00
/* We're async. This will complete later. */
tevent_req_set_callback ( req , reply_ulogoffX_done , smb1req ) ;
return ;
1996-05-04 11:50:46 +04:00
}
2020-03-12 20:11:14 +03:00
struct reply_ulogoffX_state {
struct tevent_queue * wait_queue ;
struct smbXsrv_session * session ;
} ;
static void reply_ulogoffX_wait_done ( struct tevent_req * subreq ) ;
/****************************************************************************
Async SMB1 ulogoffX .
Note , on failure here we deallocate and return NULL to allow the caller to
SMB1 return an error of ERRnomem immediately .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static struct tevent_req * reply_ulogoffX_send ( struct smb_request * smb1req ,
struct smbXsrv_session * session )
{
struct tevent_req * req ;
struct reply_ulogoffX_state * state ;
struct tevent_req * subreq ;
files_struct * fsp ;
struct smbd_server_connection * sconn = session - > client - > sconn ;
uint64_t vuid = session - > global - > session_wire_id ;
req = tevent_req_create ( smb1req , & state ,
struct reply_ulogoffX_state ) ;
if ( req = = NULL ) {
return NULL ;
}
state - > wait_queue = tevent_queue_create ( state ,
" reply_ulogoffX_wait_queue " ) ;
if ( tevent_req_nomem ( state - > wait_queue , req ) ) {
TALLOC_FREE ( req ) ;
return NULL ;
}
state - > session = session ;
/*
* Make sure that no new request will be able to use this session .
* This ensures that once all outstanding fsp - > aio_requests
* on this session are done , we are safe to close it .
*/
session - > status = NT_STATUS_USER_SESSION_DELETED ;
for ( fsp = sconn - > files ; fsp ; fsp = fsp - > next ) {
if ( fsp - > vuid ! = vuid ) {
continue ;
}
/*
* Flag the file as close in progress .
* This will prevent any more IO being
* done on it .
*/
2020-04-03 09:06:27 +03:00
fsp - > fsp_flags . closing = true ;
2020-03-12 20:11:14 +03:00
if ( fsp - > num_aio_requests > 0 ) {
/*
* Now wait until all aio requests on this fsp are
* finished .
*
* We don ' t set a callback , as we just want to block the
* wait queue and the talloc_free ( ) of fsp - > aio_request
* will remove the item from the wait queue .
*/
subreq = tevent_queue_wait_send ( fsp - > aio_requests ,
sconn - > ev_ctx ,
state - > wait_queue ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
TALLOC_FREE ( req ) ;
return NULL ;
}
}
}
/*
* Now we add our own waiter to the end of the queue ,
* this way we get notified when all pending requests are finished
* and reply to the outstanding SMB1 request .
*/
subreq = tevent_queue_wait_send ( state ,
sconn - > ev_ctx ,
state - > wait_queue ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
TALLOC_FREE ( req ) ;
return NULL ;
}
/*
* We ' re really going async - move the SMB1 request from
* a talloc stackframe above us to the sconn talloc - context .
* We need this to stick around until the wait_done
* callback is invoked .
*/
smb1req = talloc_move ( sconn , & smb1req ) ;
tevent_req_set_callback ( subreq , reply_ulogoffX_wait_done , req ) ;
return req ;
}
static void reply_ulogoffX_wait_done ( struct tevent_req * subreq )
{
struct tevent_req * req = tevent_req_callback_data (
subreq , struct tevent_req ) ;
tevent_queue_wait_recv ( subreq ) ;
TALLOC_FREE ( subreq ) ;
tevent_req_done ( req ) ;
}
static NTSTATUS reply_ulogoffX_recv ( struct tevent_req * req )
{
return tevent_req_simple_recv_ntstatus ( req ) ;
}
static void reply_ulogoffX_done ( struct tevent_req * req )
{
struct smb_request * smb1req = tevent_req_callback_data (
req , struct smb_request ) ;
struct reply_ulogoffX_state * state = tevent_req_data ( req ,
struct reply_ulogoffX_state ) ;
struct smbXsrv_session * session = state - > session ;
NTSTATUS status ;
/*
* Take the profile charge here . Not strictly
* correct but better than the other SMB1 async
* code that double - charges at the moment .
*/
START_PROFILE ( SMBulogoffX ) ;
status = reply_ulogoffX_recv ( req ) ;
TALLOC_FREE ( req ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
TALLOC_FREE ( smb1req ) ;
END_PROFILE ( SMBulogoffX ) ;
exit_server ( __location__ " : reply_ulogoffX_recv failed " ) ;
return ;
}
status = smbXsrv_session_logoff ( session ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
TALLOC_FREE ( smb1req ) ;
END_PROFILE ( SMBulogoffX ) ;
exit_server ( __location__ " : smbXsrv_session_logoff failed " ) ;
return ;
}
TALLOC_FREE ( session ) ;
2022-04-05 05:53:20 +03:00
reply_smb1_outbuf ( smb1req , 2 , 0 ) ;
2020-03-12 20:11:14 +03:00
SSVAL ( smb1req - > outbuf , smb_vwv0 , 0xff ) ; /* andx chain ends */
SSVAL ( smb1req - > outbuf , smb_vwv1 , 0 ) ; /* no andx offset */
DBG_NOTICE ( " ulogoffX vuid=%llu \n " ,
( unsigned long long ) smb1req - > vuid ) ;
smb1req - > vuid = UID_FIELD_INVALID ;
/*
* The following call is needed to push the
* reply data back out the socket after async
* return . Plus it frees smb1req .
*/
smb_request_done ( smb1req ) ;
END_PROFILE ( SMBulogoffX ) ;
}
1996-05-04 11:50:46 +04:00
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a mknew or a create .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2008-01-05 02:37:24 +03:00
void reply_mknew ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
2009-06-05 05:39:55 +04:00
struct smb_filename * smb_fname = NULL ;
2007-09-08 00:57:01 +04:00
char * fname = NULL ;
2015-04-27 02:02:55 +03:00
uint32_t fattr = 0 ;
2009-01-24 01:40:19 +03:00
struct smb_file_time ft ;
2022-07-27 22:09:48 +03:00
struct files_struct * dirfsp = NULL ;
2002-12-04 02:57:45 +03:00
files_struct * fsp ;
2007-08-14 00:29:24 +04:00
int oplock_request = 0 ;
2003-10-09 03:21:36 +04:00
NTSTATUS status ;
2015-04-27 02:02:55 +03:00
uint32_t access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE ;
uint32_t share_mode = FILE_SHARE_READ | FILE_SHARE_WRITE ;
uint32_t create_disposition ;
uint32_t create_options = 0 ;
2016-10-13 13:42:59 +03:00
uint32_t ucf_flags ;
2022-07-27 22:09:48 +03:00
NTTIME twrp = 0 ;
2007-09-11 22:31:29 +04:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
2005-07-08 08:51:27 +04:00
2002-12-04 02:57:45 +03:00
START_PROFILE ( SMBcreate ) ;
2019-12-02 18:30:50 +03:00
init_smb_file_time ( & ft ) ;
2007-07-05 20:26:27 +04:00
2007-08-14 00:29:24 +04:00
if ( req - > wct < 3 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
2009-06-05 05:39:55 +04:00
goto out ;
2007-08-14 00:29:24 +04:00
}
2002-12-04 02:57:45 +03:00
2008-11-02 14:20:47 +03:00
fattr = SVAL ( req - > vwv + 0 , 0 ) ;
2007-08-14 00:29:24 +04:00
oplock_request = CORE_OPLOCK_REQUEST ( req - > inbuf ) ;
2007-01-03 09:19:11 +03:00
2016-10-13 13:42:59 +03:00
if ( req - > cmd = = SMBmknew ) {
/* We should fail if file exists. */
create_disposition = FILE_CREATE ;
} else {
/* Create if file doesn't exist, truncate if it does. */
create_disposition = FILE_OVERWRITE_IF ;
}
2009-01-24 01:40:19 +03:00
/* mtime. */
2019-12-02 18:30:50 +03:00
ft . mtime = time_t_to_full_timespec ( srv_make_unix_date3 ( req - > vwv + 1 ) ) ;
2007-08-14 00:29:24 +04:00
2008-11-02 02:59:03 +03:00
srvstr_get_path_req ( ctx , req , & fname , ( const char * ) req - > buf + 1 ,
STR_TERMINATE , & status ) ;
2003-10-09 03:21:36 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-14 00:29:24 +04:00
reply_nterror ( req , status ) ;
2009-06-05 05:39:55 +04:00
goto out ;
2003-10-09 03:21:36 +04:00
}
2002-12-04 02:57:45 +03:00
2016-10-13 13:42:59 +03:00
ucf_flags = filename_create_ucf_flags ( req , create_disposition ) ;
2022-07-27 22:09:48 +03:00
if ( ucf_flags & UCF_GMT_PATHNAME ) {
2022-08-04 20:02:15 +03:00
extract_snapshot_token ( fname , & twrp ) ;
2022-07-27 22:09:48 +03:00
}
2023-03-30 17:02:55 +03:00
status = smb1_strip_dfs_path ( ctx , & ucf_flags , & fname ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
reply_nterror ( req , status ) ;
goto out ;
}
2022-07-27 22:09:48 +03:00
status = filename_convert_dirfsp ( ctx ,
conn ,
fname ,
ucf_flags ,
twrp ,
& dirfsp ,
& smb_fname ) ;
2009-06-17 04:23:54 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
if ( NT_STATUS_EQUAL ( status , NT_STATUS_PATH_NOT_COVERED ) ) {
reply_botherror ( req ,
NT_STATUS_PATH_NOT_COVERED ,
ERRSRV , ERRbadpath ) ;
goto out ;
}
reply_nterror ( req , status ) ;
goto out ;
}
2011-04-29 05:52:48 +04:00
if ( fattr & FILE_ATTRIBUTE_VOLUME ) {
2007-08-14 00:29:24 +04:00
DEBUG ( 0 , ( " Attempt to create file (%s) with volid set - "
2009-07-02 03:15:52 +04:00
" please report this \n " ,
smb_fname_str_dbg ( smb_fname ) ) ) ;
2005-07-08 08:51:27 +04:00
}
2008-10-21 04:43:45 +04:00
status = SMB_VFS_CREATE_FILE (
conn , /* conn */
req , /* req */
2022-07-27 22:09:48 +03:00
dirfsp , /* dirfsp */
2009-06-12 23:54:11 +04:00
smb_fname , /* fname */
2008-10-21 04:43:45 +04:00
access_mask , /* access_mask */
share_mode , /* share_access */
create_disposition , /* create_disposition*/
create_options , /* create_options */
fattr , /* file_attributes */
oplock_request , /* oplock_request */
2013-08-21 17:56:14 +04:00
NULL , /* lease */
2008-10-21 04:43:45 +04:00
0 , /* allocation_size */
2010-03-06 02:10:30 +03:00
0 , /* private_flags */
2008-10-21 04:43:45 +04:00
NULL , /* sd */
NULL , /* ea_list */
& fsp , /* result */
2014-11-26 16:12:51 +03:00
NULL , /* pinfo */
NULL , NULL ) ; /* create context */
2007-08-14 00:29:24 +04:00
2006-07-11 22:01:26 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2014-09-16 08:55:39 +04:00
if ( open_was_deferred ( req - > xconn , req - > mid ) ) {
2004-06-08 20:14:31 +04:00
/* We have re-scheduled this call. */
2009-06-05 05:39:55 +04:00
goto out ;
2004-06-08 20:14:31 +04:00
}
2019-07-30 15:54:40 +03:00
if ( NT_STATUS_EQUAL ( status , NT_STATUS_SHARING_VIOLATION ) ) {
bool ok = defer_smb1_sharing_violation ( req ) ;
if ( ok ) {
goto out ;
}
}
2007-10-11 00:34:30 +04:00
reply_openerror ( req , status ) ;
2009-06-05 05:39:55 +04:00
goto out ;
2002-12-04 02:57:45 +03:00
}
2007-08-14 00:29:24 +04:00
2009-06-05 05:39:55 +04:00
ft . atime = smb_fname - > st . st_ex_atime ; /* atime. */
2009-07-03 00:39:20 +04:00
status = smb_set_file_time ( conn , fsp , smb_fname , & ft , true ) ;
2008-03-12 17:39:38 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
END_PROFILE ( SMBcreate ) ;
2009-06-05 05:39:55 +04:00
goto out ;
2008-03-12 17:39:38 +03:00
}
2007-01-03 09:19:11 +03:00
2022-04-05 05:53:20 +03:00
reply_smb1_outbuf ( req , 1 , 0 ) ;
2007-08-14 00:29:24 +04:00
SSVAL ( req - > outbuf , smb_vwv0 , fsp - > fnum ) ;
1996-10-05 14:41:13 +04:00
2005-07-08 08:51:27 +04:00
if ( oplock_request & & lp_fake_oplocks ( SNUM ( conn ) ) ) {
2007-08-14 00:29:24 +04:00
SCVAL ( req - > outbuf , smb_flg ,
CVAL ( req - > outbuf , smb_flg ) | CORE_OPLOCK_GRANTED ) ;
2005-07-08 08:51:27 +04:00
}
2007-08-14 00:29:24 +04:00
2005-07-08 08:51:27 +04:00
if ( EXCLUSIVE_OPLOCK_TYPE ( fsp - > oplock_type ) ) {
2007-08-14 00:29:24 +04:00
SCVAL ( req - > outbuf , smb_flg ,
CVAL ( req - > outbuf , smb_flg ) | CORE_OPLOCK_GRANTED ) ;
2005-07-08 08:51:27 +04:00
}
2007-08-14 00:29:24 +04:00
2009-07-03 00:39:20 +04:00
DEBUG ( 2 , ( " reply_mknew: file %s \n " , smb_fname_str_dbg ( smb_fname ) ) ) ;
DEBUG ( 3 , ( " reply_mknew %s fd=%d dmode=0x%x \n " ,
2020-09-26 22:52:52 +03:00
smb_fname_str_dbg ( smb_fname ) , fsp_get_io_fd ( fsp ) ,
2009-07-03 00:39:20 +04:00
( unsigned int ) fattr ) ) ;
1998-08-01 02:39:15 +04:00
2009-06-05 05:39:55 +04:00
out :
TALLOC_FREE ( smb_fname ) ;
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBcreate ) ;
2007-08-14 00:29:24 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a create temporary file .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2008-01-05 02:37:24 +03:00
void reply_ctemp ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
struct smb_filename * smb_fname = NULL ;
2013-04-18 01:42:20 +04:00
char * wire_name = NULL ;
2007-09-08 00:57:01 +04:00
char * fname = NULL ;
2015-04-27 02:02:55 +03:00
uint32_t fattr ;
2022-07-27 22:23:42 +03:00
struct files_struct * dirfsp = NULL ;
2002-12-04 02:57:45 +03:00
files_struct * fsp ;
2007-08-14 19:42:39 +04:00
int oplock_request ;
char * s ;
2003-10-09 03:21:36 +04:00
NTSTATUS status ;
2013-04-18 01:42:20 +04:00
int i ;
2016-10-13 13:42:59 +03:00
uint32_t ucf_flags ;
2022-07-27 22:23:42 +03:00
NTTIME twrp = 0 ;
2007-09-11 22:31:29 +04:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
2002-12-04 02:57:45 +03:00
START_PROFILE ( SMBctemp ) ;
2007-08-14 19:42:39 +04:00
if ( req - > wct < 3 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2007-08-14 19:42:39 +04:00
}
2007-07-05 20:26:27 +04:00
2008-11-02 14:20:47 +03:00
fattr = SVAL ( req - > vwv + 0 , 0 ) ;
2007-08-14 19:42:39 +04:00
oplock_request = CORE_OPLOCK_REQUEST ( req - > inbuf ) ;
2013-04-18 01:42:20 +04:00
srvstr_get_path_req ( ctx , req , & wire_name , ( const char * ) req - > buf + 1 ,
2008-11-02 02:59:03 +03:00
STR_TERMINATE , & status ) ;
2003-10-09 03:21:36 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-14 19:42:39 +04:00
reply_nterror ( req , status ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2003-10-09 03:21:36 +04:00
}
2007-09-12 03:57:59 +04:00
2013-04-18 01:42:20 +04:00
for ( i = 0 ; i < 10 ; i + + ) {
if ( * wire_name ) {
fname = talloc_asprintf ( ctx ,
" %s/TMP%s " ,
wire_name ,
generate_random_str_list ( ctx , 5 , " 0123456789 " ) ) ;
} else {
fname = talloc_asprintf ( ctx ,
" TMP%s " ,
generate_random_str_list ( ctx , 5 , " 0123456789 " ) ) ;
}
2002-12-04 02:57:45 +03:00
2013-04-18 01:42:20 +04:00
if ( ! fname ) {
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
goto out ;
}
2016-10-13 13:42:59 +03:00
ucf_flags = filename_create_ucf_flags ( req , FILE_CREATE ) ;
2022-07-27 22:23:42 +03:00
if ( ucf_flags & UCF_GMT_PATHNAME ) {
2022-08-04 20:02:15 +03:00
extract_snapshot_token ( fname , & twrp ) ;
2022-07-27 22:23:42 +03:00
}
2023-03-30 17:03:30 +03:00
status = smb1_strip_dfs_path ( ctx , & ucf_flags , & fname ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
reply_nterror ( req , status ) ;
goto out ;
}
2022-07-27 22:23:42 +03:00
status = filename_convert_dirfsp ( ctx ,
conn ,
fname ,
ucf_flags ,
twrp ,
& dirfsp ,
& smb_fname ) ;
2013-04-18 01:42:20 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
if ( NT_STATUS_EQUAL ( status , NT_STATUS_PATH_NOT_COVERED ) ) {
reply_botherror ( req , NT_STATUS_PATH_NOT_COVERED ,
2007-08-14 19:42:39 +04:00
ERRSRV , ERRbadpath ) ;
2013-04-18 01:42:20 +04:00
goto out ;
}
reply_nterror ( req , status ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2007-03-12 20:55:24 +03:00
}
2002-12-04 02:57:45 +03:00
2013-04-18 01:42:20 +04:00
/* Create the file. */
status = SMB_VFS_CREATE_FILE (
conn , /* conn */
req , /* req */
2022-07-27 22:23:42 +03:00
dirfsp , /* dirfsp */
2013-04-18 01:42:20 +04:00
smb_fname , /* fname */
FILE_GENERIC_READ | FILE_GENERIC_WRITE , /* access_mask */
FILE_SHARE_READ | FILE_SHARE_WRITE , /* share_access */
FILE_CREATE , /* create_disposition*/
0 , /* create_options */
fattr , /* file_attributes */
oplock_request , /* oplock_request */
2013-08-21 17:56:14 +04:00
NULL , /* lease */
2013-04-18 01:42:20 +04:00
0 , /* allocation_size */
0 , /* private_flags */
NULL , /* sd */
NULL , /* ea_list */
& fsp , /* result */
2014-11-26 16:12:51 +03:00
NULL , /* pinfo */
NULL , NULL ) ; /* create context */
2013-04-18 01:42:20 +04:00
if ( NT_STATUS_EQUAL ( status , NT_STATUS_OBJECT_NAME_COLLISION ) ) {
TALLOC_FREE ( fname ) ;
2022-07-27 22:23:42 +03:00
TALLOC_FREE ( dirfsp ) ;
2013-04-18 01:42:20 +04:00
TALLOC_FREE ( smb_fname ) ;
continue ;
}
2002-12-04 02:57:45 +03:00
2013-04-18 01:42:20 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2014-09-16 08:55:39 +04:00
if ( open_was_deferred ( req - > xconn , req - > mid ) ) {
2013-04-18 01:42:20 +04:00
/* We have re-scheduled this call. */
goto out ;
}
2019-07-30 15:54:40 +03:00
if ( NT_STATUS_EQUAL (
status , NT_STATUS_SHARING_VIOLATION ) ) {
bool ok = defer_smb1_sharing_violation ( req ) ;
if ( ok ) {
goto out ;
}
}
2013-04-18 01:42:20 +04:00
reply_openerror ( req , status ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2007-08-16 04:37:07 +04:00
}
2013-04-18 01:42:20 +04:00
break ;
}
if ( i = = 10 ) {
/* Collision after 10 times... */
reply_nterror ( req , status ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2002-12-04 02:57:45 +03:00
}
2022-04-05 05:53:20 +03:00
reply_smb1_outbuf ( req , 1 , 0 ) ;
2007-08-14 19:42:39 +04:00
SSVAL ( req - > outbuf , smb_vwv0 , fsp - > fnum ) ;
2002-12-04 02:57:45 +03:00
/* the returned filename is relative to the directory */
2009-07-11 01:50:37 +04:00
s = strrchr_m ( fsp - > fsp_name - > base_name , ' / ' ) ;
2005-07-08 08:51:27 +04:00
if ( ! s ) {
2009-07-11 01:50:37 +04:00
s = fsp - > fsp_name - > base_name ;
2005-07-08 08:51:27 +04:00
} else {
2002-12-04 02:57:45 +03:00
s + + ;
2005-07-08 08:51:27 +04:00
}
2002-12-04 02:57:45 +03:00
2004-04-03 02:11:08 +04:00
#if 0
/* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
thing in the byte section . JRA */
2002-12-04 02:57:45 +03:00
SSVALS ( p , 0 , - 1 ) ; /* what is this? not in spec */
2004-04-03 02:11:08 +04:00
# endif
2007-08-14 19:42:39 +04:00
if ( message_push_string ( & req - > outbuf , s , STR_ASCII | STR_TERMINATE )
= = - 1 ) {
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2007-08-14 19:42:39 +04:00
}
2002-12-04 02:57:45 +03:00
2005-07-08 08:51:27 +04:00
if ( oplock_request & & lp_fake_oplocks ( SNUM ( conn ) ) ) {
2007-08-14 19:42:39 +04:00
SCVAL ( req - > outbuf , smb_flg ,
CVAL ( req - > outbuf , smb_flg ) | CORE_OPLOCK_GRANTED ) ;
2005-07-08 08:51:27 +04:00
}
2008-10-19 17:30:12 +04:00
2005-07-08 08:51:27 +04:00
if ( EXCLUSIVE_OPLOCK_TYPE ( fsp - > oplock_type ) ) {
2007-08-14 19:42:39 +04:00
SCVAL ( req - > outbuf , smb_flg ,
CVAL ( req - > outbuf , smb_flg ) | CORE_OPLOCK_GRANTED ) ;
2005-07-08 08:51:27 +04:00
}
2002-12-04 02:57:45 +03:00
2009-07-11 01:50:37 +04:00
DEBUG ( 2 , ( " reply_ctemp: created temp file %s \n " , fsp_str_dbg ( fsp ) ) ) ;
DEBUG ( 3 , ( " reply_ctemp %s fd=%d umode=0%o \n " , fsp_str_dbg ( fsp ) ,
2020-09-26 22:52:52 +03:00
fsp_get_io_fd ( fsp ) , ( unsigned int ) smb_fname - > st . st_ex_mode ) ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
out :
2009-05-25 00:13:07 +04:00
TALLOC_FREE ( smb_fname ) ;
2013-04-18 01:42:20 +04:00
TALLOC_FREE ( wire_name ) ;
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBctemp ) ;
2007-08-14 19:42:39 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
2000-11-15 00:56:32 +03:00
/****************************************************************************
Reply to a unlink
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-01-05 02:37:24 +03:00
void reply_unlink ( struct smb_request * req )
2000-11-15 00:56:32 +03:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
2007-09-11 22:31:29 +04:00
char * name = NULL ;
2022-07-28 21:52:36 +03:00
struct files_struct * dirfsp = NULL ;
2009-07-25 05:38:40 +04:00
struct smb_filename * smb_fname = NULL ;
2015-04-27 02:02:55 +03:00
uint32_t dirtype ;
2001-09-04 11:13:01 +04:00
NTSTATUS status ;
2021-12-01 23:31:44 +03:00
uint32_t ucf_flags = ucf_flags_from_smb_request ( req ) ;
2022-07-28 21:52:36 +03:00
NTTIME twrp = 0 ;
2007-09-11 22:31:29 +04:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
2005-10-31 23:11:58 +03:00
2005-11-02 02:49:40 +03:00
START_PROFILE ( SMBunlink ) ;
2007-07-31 11:57:33 +04:00
if ( req - > wct < 1 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
2009-07-25 05:38:40 +04:00
goto out ;
2007-07-31 11:57:33 +04:00
}
2007-07-05 20:26:27 +04:00
2008-11-02 14:20:47 +03:00
dirtype = SVAL ( req - > vwv + 0 , 0 ) ;
2007-09-11 22:31:29 +04:00
2020-09-29 22:32:02 +03:00
srvstr_get_path_req ( ctx , req , & name , ( const char * ) req - > buf + 1 ,
STR_TERMINATE , & status ) ;
2003-10-09 03:21:36 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-07-31 11:57:33 +04:00
reply_nterror ( req , status ) ;
2009-07-25 05:38:40 +04:00
goto out ;
2003-10-09 03:21:36 +04:00
}
2007-03-12 20:55:24 +03:00
2022-07-28 21:52:36 +03:00
if ( ucf_flags & UCF_GMT_PATHNAME ) {
2022-08-04 20:02:15 +03:00
extract_snapshot_token ( name , & twrp ) ;
2022-07-28 21:52:36 +03:00
}
2023-03-30 17:04:02 +03:00
status = smb1_strip_dfs_path ( ctx , & ucf_flags , & name ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
reply_nterror ( req , status ) ;
goto out ;
}
2022-07-28 21:52:36 +03:00
status = filename_convert_dirfsp ( ctx ,
conn ,
name ,
ucf_flags ,
twrp ,
& dirfsp ,
& smb_fname ) ;
2007-03-12 20:55:24 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
if ( NT_STATUS_EQUAL ( status , NT_STATUS_PATH_NOT_COVERED ) ) {
2007-07-31 11:57:33 +04:00
reply_botherror ( req , NT_STATUS_PATH_NOT_COVERED ,
ERRSRV , ERRbadpath ) ;
2009-07-25 05:38:40 +04:00
goto out ;
2007-03-12 20:55:24 +03:00
}
2007-07-31 11:57:33 +04:00
reply_nterror ( req , status ) ;
2009-07-25 05:38:40 +04:00
goto out ;
2007-03-08 01:12:58 +03:00
}
2007-09-11 22:31:29 +04:00
2009-07-25 05:38:40 +04:00
DEBUG ( 3 , ( " reply_unlink : %s \n " , smb_fname_str_dbg ( smb_fname ) ) ) ;
2007-09-11 22:31:29 +04:00
2022-07-28 21:52:36 +03:00
status = unlink_internals ( conn , req , dirtype , dirfsp , smb_fname ) ;
2004-06-08 20:14:31 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2014-09-16 08:55:39 +04:00
if ( open_was_deferred ( req - > xconn , req - > mid ) ) {
2004-06-08 20:14:31 +04:00
/* We have re-scheduled this call. */
2009-07-25 05:38:40 +04:00
goto out ;
2004-06-08 20:14:31 +04:00
}
2019-07-30 15:54:40 +03:00
if ( NT_STATUS_EQUAL ( status , NT_STATUS_SHARING_VIOLATION ) ) {
bool ok = defer_smb1_sharing_violation ( req ) ;
if ( ok ) {
goto out ;
}
}
2007-07-31 11:57:33 +04:00
reply_nterror ( req , status ) ;
2009-07-25 05:38:40 +04:00
goto out ;
2004-06-08 20:14:31 +04:00
}
2001-09-04 11:13:01 +04:00
2022-04-05 05:53:20 +03:00
reply_smb1_outbuf ( req , 0 , 0 ) ;
2009-07-25 05:38:40 +04:00
out :
TALLOC_FREE ( smb_fname ) ;
2001-08-27 12:19:43 +04:00
END_PROFILE ( SMBunlink ) ;
2007-07-31 11:57:33 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
2001-09-04 23:10:30 +04:00
/****************************************************************************
Fail for readbraw .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-11-25 01:05:59 +03:00
static void fail_readraw ( void )
2001-09-04 23:10:30 +04:00
{
2007-09-13 01:48:20 +04:00
const char * errstr = talloc_asprintf ( talloc_tos ( ) ,
" FAIL ! reply_readbraw: socket write fail (%s) " ,
strerror ( errno ) ) ;
if ( ! errstr ) {
errstr = " " ;
}
2006-12-18 07:25:21 +03:00
exit_server_cleanly ( errstr ) ;
2001-09-04 23:10:30 +04:00
}
1996-05-04 11:50:46 +04:00
2007-08-14 05:45:26 +04:00
/****************************************************************************
Return a readbraw error ( 4 bytes of zero ) .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2014-06-11 16:51:05 +04:00
static void reply_readbraw_error ( struct smbXsrv_connection * xconn )
2007-08-14 05:45:26 +04:00
{
char header [ 4 ] ;
2010-03-19 14:04:32 +03:00
2007-08-14 05:45:26 +04:00
SIVAL ( header , 0 , 0 ) ;
2010-03-19 14:04:32 +03:00
2014-06-12 10:43:26 +04:00
smbd_lock_socket ( xconn ) ;
2014-05-22 01:23:34 +04:00
if ( write_data ( xconn - > transport . sock , header , 4 ) ! = 4 ) {
2014-05-23 14:59:43 +04:00
int saved_errno = errno ;
2010-08-15 18:02:37 +04:00
/*
* Try and give an error message saying what
* client failed .
*/
DEBUG ( 0 , ( " write_data failed for client %s. "
" Error %s \n " ,
2014-05-23 14:59:43 +04:00
smbXsrv_connection_dbg ( xconn ) ,
strerror ( saved_errno ) ) ) ;
errno = saved_errno ;
2010-08-15 18:02:37 +04:00
2007-08-14 05:45:26 +04:00
fail_readraw ( ) ;
}
2014-06-12 10:43:26 +04:00
smbd_unlock_socket ( xconn ) ;
2007-08-14 05:45:26 +04:00
}
2019-12-06 15:25:21 +03:00
/*******************************************************************
Ensure we don ' t use sendfile if server smb signing is active .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2023-05-25 08:50:43 +03:00
static bool lp_use_sendfile ( struct smbXsrv_connection * xconn ,
int snum ,
struct smb1_signing_state * signing_state )
2019-12-06 15:25:21 +03:00
{
bool sign_active = false ;
/* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
2023-05-25 08:50:43 +03:00
if ( xconn - > protocol < PROTOCOL_NT1 ) {
2019-12-06 15:25:21 +03:00
return false ;
}
if ( signing_state ) {
2022-03-08 06:31:34 +03:00
sign_active = smb1_signing_is_active ( signing_state ) ;
2019-12-06 15:25:21 +03:00
}
return ( lp__use_sendfile ( snum ) & &
( get_remote_arch ( ) ! = RA_WIN95 ) & &
! sign_active ) ;
}
2002-09-25 19:19:00 +04:00
/****************************************************************************
Use sendfile in readbraw .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-01-31 01:45:35 +03:00
static void send_file_readbraw ( connection_struct * conn ,
struct smb_request * req ,
files_struct * fsp ,
2012-04-05 08:53:08 +04:00
off_t startpos ,
2009-01-31 01:45:35 +03:00
size_t nread ,
ssize_t mincount )
2002-09-25 19:19:00 +04:00
{
2014-06-11 16:51:05 +04:00
struct smbXsrv_connection * xconn = req - > xconn ;
2007-08-14 05:45:26 +04:00
char * outbuf = NULL ;
2002-09-25 19:19:00 +04:00
ssize_t ret = 0 ;
/*
2023-07-18 12:30:18 +03:00
* We can only use sendfile on a non - chained packet
2004-07-01 03:00:40 +04:00
* but we can use on a non - oplocked file . tridge proved this
* on a train in Germany : - ) . JRA .
* reply_readbraw has already checked the length .
2002-09-25 19:19:00 +04:00
*/
2022-02-11 11:37:35 +03:00
if ( ! req_is_in_chain ( req ) & &
( nread > 0 ) & &
! fsp_is_alternate_stream ( fsp ) & &
2023-05-25 08:50:43 +03:00
lp_use_sendfile ( xconn , SNUM ( conn ) , xconn - > smb1 . signing_state ) ) {
2009-01-14 00:02:44 +03:00
ssize_t sendfile_read = - 1 ;
2007-08-14 05:45:26 +04:00
char header [ 4 ] ;
DATA_BLOB header_blob ;
_smb_setlen ( header , nread ) ;
2007-08-14 10:18:55 +04:00
header_blob = data_blob_const ( header , 4 ) ;
2007-08-14 05:45:26 +04:00
2014-05-22 01:23:34 +04:00
sendfile_read = SMB_VFS_SENDFILE ( xconn - > transport . sock , fsp ,
2010-08-15 10:54:23 +04:00
& header_blob , startpos ,
nread ) ;
if ( sendfile_read = = - 1 ) {
2007-08-14 05:45:26 +04:00
/* Returning ENOSYS means no data at all was sent.
* Do this as a normal read . */
2004-12-21 01:01:42 +03:00
if ( errno = = ENOSYS ) {
goto normal_readbraw ;
}
2002-09-25 19:19:00 +04:00
/*
2004-11-25 01:05:59 +03:00
* Special hack for broken Linux with no working sendfile . If we
* return EINTR we sent the header but not the rest of the data .
* Fake this up by doing read / write calls .
2002-09-25 19:19:00 +04:00
*/
2004-11-25 01:05:59 +03:00
if ( errno = = EINTR ) {
/* Ensure we don't do this again. */
2004-08-06 21:49:00 +04:00
set_use_sendfile ( SNUM ( conn ) , False ) ;
2004-11-25 01:05:59 +03:00
DEBUG ( 0 , ( " send_file_readbraw: sendfile not available. Faking.. \n " ) ) ;
2014-06-12 10:40:25 +04:00
if ( fake_sendfile ( xconn , fsp , startpos , nread ) = = - 1 ) {
2009-07-11 01:50:37 +04:00
DEBUG ( 0 , ( " send_file_readbraw: "
" fake_sendfile failed for "
" file %s (%s). \n " ,
fsp_str_dbg ( fsp ) ,
strerror ( errno ) ) ) ;
2006-12-18 07:25:21 +03:00
exit_server_cleanly ( " send_file_readbraw fake_sendfile failed " ) ;
2004-11-25 01:05:59 +03:00
}
return ;
2004-08-06 21:49:00 +04:00
}
2002-09-25 19:19:00 +04:00
2009-07-11 01:50:37 +04:00
DEBUG ( 0 , ( " send_file_readbraw: sendfile failed for "
" file %s (%s). Terminating \n " ,
fsp_str_dbg ( fsp ) , strerror ( errno ) ) ) ;
2006-12-18 07:25:21 +03:00
exit_server_cleanly ( " send_file_readbraw sendfile failed " ) ;
2009-02-21 00:28:36 +03:00
} else if ( sendfile_read = = 0 ) {
/*
* Some sendfile implementations return 0 to indicate
* that there was a short read , but nothing was
* actually written to the socket . In this case ,
* fallback to the normal read path so the header gets
* the correct byte count .
*/
DEBUG ( 3 , ( " send_file_readbraw: sendfile sent zero "
" bytes falling back to the normal read: "
2009-07-11 01:50:37 +04:00
" %s \n " , fsp_str_dbg ( fsp ) ) ) ;
2009-02-21 00:28:36 +03:00
goto normal_readbraw ;
2002-09-25 19:19:00 +04:00
}
2009-01-14 00:02:44 +03:00
/* Deal with possible short send. */
2009-01-14 02:36:09 +03:00
if ( sendfile_read ! = 4 + nread ) {
2014-06-12 10:42:16 +04:00
ret = sendfile_short_send ( xconn , fsp ,
sendfile_read , 4 , nread ) ;
if ( ret = = - 1 ) {
fail_readraw ( ) ;
}
2009-01-14 02:36:09 +03:00
}
2007-05-09 04:52:46 +04:00
return ;
2002-09-25 19:19:00 +04:00
}
2007-06-01 23:34:08 +04:00
normal_readbraw :
2011-06-07 05:30:12 +04:00
outbuf = talloc_array ( NULL , char , nread + 4 ) ;
2007-08-14 05:45:26 +04:00
if ( ! outbuf ) {
2011-06-07 05:30:12 +04:00
DEBUG ( 0 , ( " send_file_readbraw: talloc_array failed for size %u. \n " ,
2007-08-14 12:29:36 +04:00
( unsigned ) ( nread + 4 ) ) ) ;
2014-06-11 16:51:05 +04:00
reply_readbraw_error ( xconn ) ;
2007-08-14 05:45:26 +04:00
return ;
}
2002-09-25 19:19:00 +04:00
if ( nread > 0 ) {
ret = read_file ( fsp , outbuf + 4 , startpos , nread ) ;
2003-10-09 05:46:01 +04:00
#if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2002-09-25 19:19:00 +04:00
if ( ret < mincount )
ret = 0 ;
2003-10-09 05:46:01 +04:00
# else
if ( ret < nread )
ret = 0 ;
# endif
2002-09-25 19:19:00 +04:00
}
_smb_setlen ( outbuf , ret ) ;
2014-05-22 01:23:34 +04:00
if ( write_data ( xconn - > transport . sock , outbuf , 4 + ret ) ! = 4 + ret ) {
2014-05-23 14:59:43 +04:00
int saved_errno = errno ;
2010-08-15 18:02:37 +04:00
/*
* Try and give an error message saying what
* client failed .
*/
2014-05-23 14:59:43 +04:00
DEBUG ( 0 , ( " write_data failed for client %s. Error %s \n " ,
smbXsrv_connection_dbg ( xconn ) ,
strerror ( saved_errno ) ) ) ;
errno = saved_errno ;
2010-08-15 18:02:37 +04:00
2002-09-25 19:19:00 +04:00
fail_readraw ( ) ;
2010-08-15 18:02:37 +04:00
}
2007-08-14 05:45:26 +04:00
TALLOC_FREE ( outbuf ) ;
2002-09-25 19:19:00 +04:00
}
1996-05-04 11:50:46 +04:00
/****************************************************************************
2001-09-04 23:10:30 +04:00
Reply to a readbraw ( core + protocol ) .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
2008-01-05 02:37:24 +03:00
void reply_readbraw ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
2014-06-11 16:51:05 +04:00
struct smbXsrv_connection * xconn = req - > xconn ;
2001-11-14 05:35:56 +03:00
ssize_t maxcount , mincount ;
2001-09-04 23:10:30 +04:00
size_t nread = 0 ;
2012-04-05 08:53:08 +04:00
off_t startpos ;
2001-09-04 23:10:30 +04:00
files_struct * fsp ;
2009-03-14 00:15:28 +03:00
struct lock_struct lock ;
2012-04-05 08:53:08 +04:00
off_t size = 0 ;
2019-09-09 08:57:34 +03:00
NTSTATUS status ;
2007-08-14 05:45:26 +04:00
2001-09-04 23:10:30 +04:00
START_PROFILE ( SMBreadbraw ) ;
1996-05-04 11:50:46 +04:00
2022-03-08 06:51:06 +03:00
if ( smb1_srv_is_signing_active ( xconn ) | | req - > encrypted ) {
2007-12-27 04:12:36 +03:00
exit_server_cleanly ( " reply_readbraw: SMB signing/sealing is active - "
2007-08-14 05:45:26 +04:00
" raw reads/writes are disallowed. " ) ;
}
if ( req - > wct < 8 ) {
2014-06-11 16:51:05 +04:00
reply_readbraw_error ( xconn ) ;
2007-08-14 05:45:26 +04:00
END_PROFILE ( SMBreadbraw ) ;
return ;
2003-07-17 04:53:37 +04:00
}
2014-05-23 11:26:26 +04:00
if ( xconn - > smb1 . echo_handler . trusted_fde ) {
2010-05-26 19:52:10 +04:00
DEBUG ( 2 , ( " SMBreadbraw rejected with NOT_SUPPORTED because of "
" 'async smb echo handler = yes' \n " ) ) ;
2014-06-11 16:51:05 +04:00
reply_readbraw_error ( xconn ) ;
2010-03-22 11:11:05 +03:00
END_PROFILE ( SMBreadbraw ) ;
return ;
}
2001-09-04 23:10:30 +04:00
/*
* Special check if an oplock break has been issued
* and the readraw request croses on the wire , we must
* return a zero length response here .
*/
1997-10-02 03:32:22 +04:00
2008-11-02 14:20:47 +03:00
fsp = file_fsp ( req , SVAL ( req - > vwv + 0 , 0 ) ) ;
1996-05-04 11:50:46 +04:00
2007-08-25 23:47:57 +04:00
/*
2007-08-14 05:45:26 +04:00
* We have to do a check_fsp by hand here , as
* we must always return 4 zero bytes on error ,
* not a NTSTATUS .
*/
2020-04-02 10:13:56 +03:00
if ( fsp = = NULL | |
conn = = NULL | |
conn ! = fsp - > conn | |
req - > vuid ! = fsp - > vuid | |
2020-04-02 19:21:11 +03:00
fsp - > fsp_flags . is_directory | |
2020-09-26 22:52:52 +03:00
fsp_get_io_fd ( fsp ) = = - 1 )
2020-04-02 10:13:56 +03:00
{
2001-09-04 23:10:30 +04:00
/*
* fsp could be NULL here so use the value from the packet . JRA .
*/
2007-08-14 05:45:26 +04:00
DEBUG ( 3 , ( " reply_readbraw: fnum %d not valid "
" - cache prime? \n " ,
2008-11-02 14:20:47 +03:00
( int ) SVAL ( req - > vwv + 0 , 0 ) ) ) ;
2014-06-11 16:51:05 +04:00
reply_readbraw_error ( xconn ) ;
2001-09-04 23:10:30 +04:00
END_PROFILE ( SMBreadbraw ) ;
2007-08-14 05:45:26 +04:00
return ;
2001-09-04 23:10:30 +04:00
}
1999-12-13 16:27:58 +03:00
2007-08-14 05:45:26 +04:00
/* Do a "by hand" version of CHECK_READ. */
2020-04-02 18:18:43 +03:00
if ( ! ( fsp - > fsp_flags . can_read | |
2007-08-14 05:45:26 +04:00
( ( req - > flags2 & FLAGS2_READ_PERMIT_EXECUTE ) & &
( fsp - > access_mask & FILE_EXECUTE ) ) ) ) {
DEBUG ( 3 , ( " reply_readbraw: fnum %d not readable. \n " ,
2008-11-02 14:20:47 +03:00
( int ) SVAL ( req - > vwv + 0 , 0 ) ) ) ;
2014-06-11 16:51:05 +04:00
reply_readbraw_error ( xconn ) ;
2007-08-14 05:45:26 +04:00
END_PROFILE ( SMBreadbraw ) ;
return ;
}
1999-12-13 16:27:58 +03:00
2008-11-02 14:20:47 +03:00
startpos = IVAL_TO_SMB_OFF_T ( req - > vwv + 1 , 0 ) ;
2007-08-14 10:18:55 +04:00
if ( req - > wct = = 10 ) {
2001-09-04 23:10:30 +04:00
/*
* This is a large offset ( 64 bit ) read .
*/
1999-12-13 16:27:58 +03:00
2012-04-05 08:53:08 +04:00
startpos | = ( ( ( off_t ) IVAL ( req - > vwv + 8 , 0 ) ) < < 32 ) ;
1999-12-13 16:27:58 +03:00
2001-09-04 23:10:30 +04:00
if ( startpos < 0 ) {
2007-08-14 05:45:26 +04:00
DEBUG ( 0 , ( " reply_readbraw: negative 64 bit "
" readraw offset (%.0f) ! \n " ,
( double ) startpos ) ) ;
2014-06-11 16:51:05 +04:00
reply_readbraw_error ( xconn ) ;
2001-09-04 23:10:30 +04:00
END_PROFILE ( SMBreadbraw ) ;
2007-08-14 05:45:26 +04:00
return ;
2009-11-18 03:06:08 +03:00
}
2001-09-04 23:10:30 +04:00
}
2007-08-14 05:45:26 +04:00
2008-11-02 14:20:47 +03:00
maxcount = ( SVAL ( req - > vwv + 3 , 0 ) & 0xFFFF ) ;
mincount = ( SVAL ( req - > vwv + 4 , 0 ) & 0xFFFF ) ;
2001-09-04 23:10:30 +04:00
/* ensure we don't overrun the packet size */
maxcount = MIN ( 65535 , maxcount ) ;
2021-11-17 02:00:03 +03:00
init_strict_lock_struct ( fsp ,
( uint64_t ) req - > smbpid ,
( uint64_t ) startpos ,
( uint64_t ) maxcount ,
READ_LOCK ,
lp_posix_cifsu_locktype ( fsp ) ,
& lock ) ;
2009-03-14 00:15:28 +03:00
2017-07-09 15:34:10 +03:00
if ( ! SMB_VFS_STRICT_LOCK_CHECK ( conn , fsp , & lock ) ) {
2014-06-11 16:51:05 +04:00
reply_readbraw_error ( xconn ) ;
2007-08-14 05:45:26 +04:00
END_PROFILE ( SMBreadbraw ) ;
return ;
}
1996-05-04 11:50:46 +04:00
2019-09-09 08:57:34 +03:00
status = vfs_stat_fsp ( fsp ) ;
if ( NT_STATUS_IS_OK ( status ) ) {
2009-11-18 03:06:08 +03:00
size = fsp - > fsp_name - > st . st_ex_size ;
2007-08-14 05:45:26 +04:00
}
if ( startpos > = size ) {
nread = 0 ;
} else {
2007-08-25 23:47:57 +04:00
nread = MIN ( maxcount , ( size - startpos ) ) ;
2001-09-04 23:10:30 +04:00
}
1998-07-31 01:18:57 +04:00
2003-10-09 05:46:01 +04:00
#if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2001-09-04 23:10:30 +04:00
if ( nread < mincount )
nread = 0 ;
2003-10-09 05:46:01 +04:00
# endif
2008-10-19 17:30:12 +04:00
2012-06-14 15:10:33 +04:00
DEBUG ( 3 , ( " reply_readbraw: %s start=%.0f max=%lu "
2007-08-14 05:45:26 +04:00
" min=%lu nread=%lu \n " ,
2012-06-14 15:10:33 +04:00
fsp_fnum_dbg ( fsp ) , ( double ) startpos ,
2007-08-14 05:45:26 +04:00
( unsigned long ) maxcount ,
( unsigned long ) mincount ,
( unsigned long ) nread ) ) ;
2008-10-19 17:30:12 +04:00
2009-01-31 01:44:21 +03:00
send_file_readbraw ( conn , req , fsp , startpos , nread , mincount ) ;
1996-05-04 11:50:46 +04:00
2007-08-14 05:45:26 +04:00
DEBUG ( 5 , ( " reply_readbraw finished \n " ) ) ;
2009-03-14 00:15:28 +03:00
2001-09-04 23:10:30 +04:00
END_PROFILE ( SMBreadbraw ) ;
2009-03-14 00:15:28 +03:00
return ;
1996-05-04 11:50:46 +04:00
}
2005-04-27 22:32:37 +04:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_LOCKING
1996-05-04 11:50:46 +04:00
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a lockread ( core + protocol ) .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2019-06-13 13:48:31 +03:00
static void reply_lockread_locked ( struct tevent_req * subreq ) ;
2008-01-05 02:37:24 +03:00
void reply_lockread ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2019-06-13 13:48:31 +03:00
struct tevent_req * subreq = NULL ;
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
2007-08-15 00:20:51 +04:00
files_struct * fsp ;
2019-06-13 13:48:31 +03:00
struct smbd_lock_element * lck = NULL ;
2007-08-15 00:20:51 +04:00
2001-08-27 12:19:43 +04:00
START_PROFILE ( SMBlockread ) ;
1996-05-04 11:50:46 +04:00
2007-08-15 00:20:51 +04:00
if ( req - > wct < 5 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBlockread ) ;
return ;
}
2008-11-02 14:20:47 +03:00
fsp = file_fsp ( req , SVAL ( req - > vwv + 0 , 0 ) ) ;
2007-08-15 00:20:51 +04:00
2008-06-19 18:31:59 +04:00
if ( ! check_fsp ( conn , req , fsp ) ) {
2007-08-15 00:20:51 +04:00
END_PROFILE ( SMBlockread ) ;
return ;
}
2008-11-06 22:16:04 +03:00
if ( ! CHECK_READ ( fsp , req ) ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_ACCESS_DENIED ) ;
2007-08-15 00:20:51 +04:00
END_PROFILE ( SMBlockread ) ;
return ;
2005-07-08 08:51:27 +04:00
}
1996-05-04 11:50:46 +04:00
2019-06-13 13:48:31 +03:00
lck = talloc ( req , struct smbd_lock_element ) ;
if ( lck = = NULL ) {
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
END_PROFILE ( SMBlockread ) ;
return ;
}
2007-08-15 00:20:51 +04:00
2001-08-27 12:19:43 +04:00
/*
* NB . Discovered by Menny Hamburger at Mainsoft . This is a core +
2023-07-18 12:30:18 +03:00
* protocol request that predates the read / write lock concept .
2001-08-27 12:19:43 +04:00
* Thus instead of asking for a read lock here we need to ask
* for a write lock . JRA .
2014-03-04 17:07:26 +04:00
* Note that the requested lock size is unaffected by max_send .
2001-08-27 12:19:43 +04:00
*/
2008-10-19 17:30:12 +04:00
2019-06-13 13:48:31 +03:00
* lck = ( struct smbd_lock_element ) {
2019-08-08 20:26:28 +03:00
. req_guid = smbd_request_guid ( req , 0 ) ,
2019-06-13 13:48:31 +03:00
. smblctx = req - > smbpid ,
. brltype = WRITE_LOCK ,
2021-11-17 01:26:44 +03:00
. lock_flav = WINDOWS_LOCK ,
2019-06-13 13:48:31 +03:00
. count = SVAL ( req - > vwv + 1 , 0 ) ,
. offset = IVAL_TO_SMB_OFF_T ( req - > vwv + 2 , 0 ) ,
} ;
subreq = smbd_smb1_do_locks_send (
fsp ,
req - > sconn - > ev_ctx ,
& req ,
fsp ,
0 ,
false , /* large_offset */
1 ,
lck ) ;
if ( subreq = = NULL ) {
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBlockread ) ;
2007-08-15 00:20:51 +04:00
return ;
2001-08-27 12:19:43 +04:00
}
2019-06-13 13:48:31 +03:00
tevent_req_set_callback ( subreq , reply_lockread_locked , NULL ) ;
END_PROFILE ( SMBlockread ) ;
}
static void reply_lockread_locked ( struct tevent_req * subreq )
{
struct smb_request * req = NULL ;
ssize_t nread = - 1 ;
char * data = NULL ;
NTSTATUS status ;
bool ok ;
off_t startpos ;
size_t numtoread , maxtoread ;
struct files_struct * fsp = NULL ;
char * p = NULL ;
START_PROFILE ( SMBlockread ) ;
ok = smbd_smb1_do_locks_extract_smbreq ( subreq , talloc_tos ( ) , & req ) ;
SMB_ASSERT ( ok ) ;
status = smbd_smb1_do_locks_recv ( subreq ) ;
TALLOC_FREE ( subreq ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
reply_nterror ( req , status ) ;
goto send ;
}
fsp = file_fsp ( req , SVAL ( req - > vwv + 0 , 0 ) ) ;
if ( fsp = = NULL ) {
reply_nterror ( req , NT_STATUS_INTERNAL_ERROR ) ;
goto send ;
}
numtoread = SVAL ( req - > vwv + 1 , 0 ) ;
startpos = IVAL_TO_SMB_OFF_T ( req - > vwv + 2 , 0 ) ;
1998-08-01 02:39:15 +04:00
2003-10-09 05:46:01 +04:00
/*
2014-03-04 17:07:26 +04:00
* However the requested READ size IS affected by max_send . Insanity . . . . JRA .
2003-10-09 05:46:01 +04:00
*/
2020-07-19 14:59:00 +03:00
maxtoread = req - > xconn - > smb1 . sessions . max_send - ( MIN_SMB_SIZE + 5 * 2 + 3 ) ;
2003-10-09 05:46:01 +04:00
2014-03-04 17:07:26 +04:00
if ( numtoread > maxtoread ) {
2019-06-03 22:31:26 +03:00
DBG_WARNING ( " requested read size (%zu) is greater than "
" maximum allowed (%zu/%d). "
" Returning short read of maximum allowed for "
" compatibility with Windows 2000. \n " ,
numtoread ,
maxtoread ,
2019-06-13 13:48:31 +03:00
req - > xconn - > smb1 . sessions . max_send ) ;
2014-03-04 17:07:26 +04:00
numtoread = maxtoread ;
2003-10-09 23:01:31 +04:00
}
2014-03-04 17:07:26 +04:00
2022-04-05 05:53:20 +03:00
reply_smb1_outbuf ( req , 5 , numtoread + 3 ) ;
2014-03-04 17:07:26 +04:00
data = smb_buf ( req - > outbuf ) + 3 ;
2001-08-27 12:19:43 +04:00
nread = read_file ( fsp , data , startpos , numtoread ) ;
1998-08-01 02:39:15 +04:00
2001-08-27 12:19:43 +04:00
if ( nread < 0 ) {
2009-07-11 05:23:00 +04:00
reply_nterror ( req , map_nt_error_from_unix ( errno ) ) ;
2019-06-13 13:48:31 +03:00
goto send ;
2001-08-27 12:19:43 +04:00
}
2008-10-19 17:30:12 +04:00
2022-04-05 04:40:11 +03:00
srv_smb1_set_message ( ( char * ) req - > outbuf , 5 , nread + 3 , False ) ;
2007-08-15 00:20:51 +04:00
SSVAL ( req - > outbuf , smb_vwv0 , nread ) ;
SSVAL ( req - > outbuf , smb_vwv5 , nread + 3 ) ;
2007-09-08 00:57:01 +04:00
p = smb_buf ( req - > outbuf ) ;
SCVAL ( p , 0 , 0 ) ; /* pad byte. */
SSVAL ( p , 1 , nread ) ;
2008-10-19 17:30:12 +04:00
2012-06-14 15:10:33 +04:00
DEBUG ( 3 , ( " lockread %s num=%d nread=%d \n " ,
fsp_fnum_dbg ( fsp ) , ( int ) numtoread , ( int ) nread ) ) ;
1998-08-01 02:39:15 +04:00
2019-06-13 13:48:31 +03:00
send :
2022-03-31 22:09:13 +03:00
ok = smb1_srv_send ( req - > xconn ,
2023-06-05 16:45:35 +03:00
( char * ) req - > outbuf ,
true ,
req - > seqnum + 1 ,
IS_CONN_ENCRYPTED ( req - > conn ) ) ;
2019-06-13 13:48:31 +03:00
if ( ! ok ) {
2022-03-31 22:09:13 +03:00
exit_server_cleanly ( " reply_lock_done: smb1_srv_send failed. " ) ;
2019-06-13 13:48:31 +03:00
}
TALLOC_FREE ( req ) ;
2001-08-27 12:19:43 +04:00
END_PROFILE ( SMBlockread ) ;
2007-08-15 00:20:51 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
2005-04-27 22:32:37 +04:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_ALL
1996-05-04 11:50:46 +04:00
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a read .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
2008-01-05 02:37:24 +03:00
void reply_read ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
2002-09-25 19:19:00 +04:00
size_t numtoread ;
2014-03-04 17:07:26 +04:00
size_t maxtoread ;
2002-09-25 19:19:00 +04:00
ssize_t nread = 0 ;
char * data ;
2012-04-05 08:53:08 +04:00
off_t startpos ;
2007-08-14 22:33:29 +04:00
files_struct * fsp ;
2009-03-14 00:15:28 +03:00
struct lock_struct lock ;
2014-06-11 17:12:32 +04:00
struct smbXsrv_connection * xconn = req - > xconn ;
2007-08-14 22:33:29 +04:00
2002-09-25 19:19:00 +04:00
START_PROFILE ( SMBread ) ;
1996-05-04 11:50:46 +04:00
2007-08-14 22:33:29 +04:00
if ( req - > wct < 3 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBread ) ;
return ;
2005-07-08 08:51:27 +04:00
}
2001-08-27 12:19:43 +04:00
2008-11-02 14:20:47 +03:00
fsp = file_fsp ( req , SVAL ( req - > vwv + 0 , 0 ) ) ;
2007-08-14 22:33:29 +04:00
2008-06-19 18:31:59 +04:00
if ( ! check_fsp ( conn , req , fsp ) ) {
2007-08-14 22:33:29 +04:00
END_PROFILE ( SMBread ) ;
return ;
}
2008-11-06 22:16:04 +03:00
if ( ! CHECK_READ ( fsp , req ) ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_ACCESS_DENIED ) ;
2007-08-14 22:33:29 +04:00
END_PROFILE ( SMBread ) ;
return ;
}
2008-11-02 14:20:47 +03:00
numtoread = SVAL ( req - > vwv + 1 , 0 ) ;
startpos = IVAL_TO_SMB_OFF_T ( req - > vwv + 2 , 0 ) ;
2001-08-27 12:19:43 +04:00
2003-10-09 05:46:01 +04:00
/*
2014-03-04 17:07:26 +04:00
* The requested read size cannot be greater than max_send . JRA .
2003-10-09 05:46:01 +04:00
*/
2020-07-19 14:59:00 +03:00
maxtoread = xconn - > smb1 . sessions . max_send - ( MIN_SMB_SIZE + 5 * 2 + 3 ) ;
2014-03-04 17:07:26 +04:00
if ( numtoread > maxtoread ) {
DEBUG ( 0 , ( " reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
2003-10-09 23:01:31 +04:00
Returning short read of maximum allowed for compatibility with Windows 2000. \ n " ,
2014-03-04 17:07:26 +04:00
( unsigned int ) numtoread , ( unsigned int ) maxtoread ,
2014-05-21 12:56:26 +04:00
( unsigned int ) xconn - > smb1 . sessions . max_send ) ) ;
2014-03-04 17:07:26 +04:00
numtoread = maxtoread ;
2003-10-09 23:01:31 +04:00
}
2003-10-09 05:46:01 +04:00
2022-04-05 05:53:20 +03:00
reply_smb1_outbuf ( req , 5 , numtoread + 3 ) ;
2007-08-14 22:33:29 +04:00
data = smb_buf ( req - > outbuf ) + 3 ;
2008-10-19 17:30:12 +04:00
2021-11-17 02:00:03 +03:00
init_strict_lock_struct ( fsp ,
( uint64_t ) req - > smbpid ,
( uint64_t ) startpos ,
( uint64_t ) numtoread ,
READ_LOCK ,
lp_posix_cifsu_locktype ( fsp ) ,
& lock ) ;
2009-03-14 00:15:28 +03:00
2017-07-09 15:34:10 +03:00
if ( ! SMB_VFS_STRICT_LOCK_CHECK ( conn , fsp , & lock ) ) {
2009-12-19 01:25:39 +03:00
reply_nterror ( req , NT_STATUS_FILE_LOCK_CONFLICT ) ;
2002-09-25 19:19:00 +04:00
END_PROFILE ( SMBread ) ;
2007-08-14 22:33:29 +04:00
return ;
2002-09-25 19:19:00 +04:00
}
1996-05-04 11:50:46 +04:00
2002-09-25 19:19:00 +04:00
if ( numtoread > 0 )
nread = read_file ( fsp , data , startpos , numtoread ) ;
2001-08-27 12:19:43 +04:00
2002-09-25 19:19:00 +04:00
if ( nread < 0 ) {
2009-07-11 05:23:00 +04:00
reply_nterror ( req , map_nt_error_from_unix ( errno ) ) ;
2017-07-09 15:21:21 +03:00
goto out ;
2002-09-25 19:19:00 +04:00
}
2007-08-14 22:33:29 +04:00
2022-04-05 04:40:11 +03:00
srv_smb1_set_message ( ( char * ) req - > outbuf , 5 , nread + 3 , False ) ;
2007-08-14 22:33:29 +04:00
SSVAL ( req - > outbuf , smb_vwv0 , nread ) ;
SSVAL ( req - > outbuf , smb_vwv5 , nread + 3 ) ;
SCVAL ( smb_buf ( req - > outbuf ) , 0 , 1 ) ;
SSVAL ( smb_buf ( req - > outbuf ) , 1 , nread ) ;
2008-10-19 17:30:12 +04:00
2012-06-14 15:10:33 +04:00
DEBUG ( 3 , ( " read %s num=%d nread=%d \n " ,
fsp_fnum_dbg ( fsp ) , ( int ) numtoread , ( int ) nread ) ) ;
1998-08-01 02:39:15 +04:00
2017-07-09 15:21:21 +03:00
out :
2002-09-25 19:19:00 +04:00
END_PROFILE ( SMBread ) ;
2007-08-14 22:33:29 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
2007-05-16 04:07:38 +04:00
/****************************************************************************
Setup readX header .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2018-05-16 18:05:38 +03:00
size_t setup_readX_header ( char * outbuf , size_t smb_maxcnt )
2007-05-16 04:07:38 +04:00
{
2018-05-16 18:05:38 +03:00
size_t outsize ;
2007-08-12 15:40:27 +04:00
2022-04-05 04:40:11 +03:00
outsize = srv_smb1_set_message ( outbuf , 12 , smb_maxcnt + 1 /* padding byte */ ,
2014-08-15 09:04:33 +04:00
False ) ;
2007-05-16 04:07:38 +04:00
2007-09-13 01:48:20 +04:00
memset ( outbuf + smb_vwv0 , ' \0 ' , 24 ) ; /* valgrind init. */
SCVAL ( outbuf , smb_vwv0 , 0xFF ) ;
2007-05-16 04:07:38 +04:00
SSVAL ( outbuf , smb_vwv2 , 0xFFFF ) ; /* Remaining - must be -1. */
SSVAL ( outbuf , smb_vwv5 , smb_maxcnt ) ;
2008-11-22 01:17:31 +03:00
SSVAL ( outbuf , smb_vwv6 ,
2012-03-03 03:33:15 +04:00
( smb_wct - 4 ) /* offset from smb header to wct */
2008-11-22 01:17:31 +03:00
+ 1 /* the wct field */
+ 12 * sizeof ( uint16_t ) /* vwv */
2014-08-15 09:04:33 +04:00
+ 2 /* the buflen field */
+ 1 ) ; /* padding byte */
2007-05-16 04:07:38 +04:00
SSVAL ( outbuf , smb_vwv7 , ( smb_maxcnt > > 16 ) ) ;
2014-08-15 09:04:33 +04:00
SCVAL ( smb_buf ( outbuf ) , 0 , 0 ) ; /* padding byte */
2007-05-16 04:07:38 +04:00
/* Reset the outgoing length, set_message truncates at 0x1FFFF. */
2014-08-15 09:04:33 +04:00
_smb_setlen_large ( outbuf ,
smb_size + 12 * 2 + smb_maxcnt - 4 + 1 /* pad */ ) ;
2007-05-16 04:07:38 +04:00
return outsize ;
}
2002-09-25 19:19:00 +04:00
/****************************************************************************
Reply to a read and X - possibly using sendfile .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-08-12 13:16:54 +04:00
static void send_file_readX ( connection_struct * conn , struct smb_request * req ,
2012-04-05 08:53:08 +04:00
files_struct * fsp , off_t startpos ,
2007-08-12 13:16:54 +04:00
size_t smb_maxcnt )
2002-09-25 19:19:00 +04:00
{
2014-06-11 17:12:32 +04:00
struct smbXsrv_connection * xconn = req - > xconn ;
2002-09-25 19:19:00 +04:00
ssize_t nread = - 1 ;
2009-05-13 03:32:32 +04:00
struct lock_struct lock ;
2009-07-11 05:23:00 +04:00
int saved_errno = 0 ;
2019-09-09 08:57:34 +03:00
NTSTATUS status ;
2007-08-12 13:16:54 +04:00
2021-11-17 02:00:03 +03:00
init_strict_lock_struct ( fsp ,
( uint64_t ) req - > smbpid ,
( uint64_t ) startpos ,
( uint64_t ) smb_maxcnt ,
READ_LOCK ,
lp_posix_cifsu_locktype ( fsp ) ,
& lock ) ;
2009-05-13 03:32:32 +04:00
2017-07-09 15:34:10 +03:00
if ( ! SMB_VFS_STRICT_LOCK_CHECK ( conn , fsp , & lock ) ) {
2009-12-19 01:25:39 +03:00
reply_nterror ( req , NT_STATUS_FILE_LOCK_CONFLICT ) ;
2009-05-13 03:32:32 +04:00
return ;
}
2002-09-25 19:19:00 +04:00
/*
2007-09-13 01:48:20 +04:00
* We can only use sendfile on a non - chained packet
2004-07-01 03:00:40 +04:00
* but we can use on a non - oplocked file . tridge proved this
* on a train in Germany : - ) . JRA .
2002-09-25 19:19:00 +04:00
*/
2009-01-31 01:44:21 +03:00
if ( ! req_is_in_chain ( req ) & &
2013-03-16 02:05:31 +04:00
! req - > encrypted & &
2022-02-11 11:37:35 +03:00
! fsp_is_alternate_stream ( fsp ) & &
2023-05-25 08:50:43 +03:00
lp_use_sendfile ( xconn , SNUM ( conn ) , xconn - > smb1 . signing_state ) ) {
2015-04-27 02:02:55 +03:00
uint8_t headerbuf [ smb_size + 12 * 2 + 1 /* padding byte */ ] ;
2002-09-25 19:19:00 +04:00
DATA_BLOB header ;
2019-09-09 08:57:34 +03:00
status = vfs_stat_fsp ( fsp ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
reply_nterror ( req , status ) ;
2017-07-09 15:21:21 +03:00
goto out ;
2013-03-25 20:54:50 +04:00
}
if ( ! S_ISREG ( fsp - > fsp_name - > st . st_ex_mode ) | |
( startpos > fsp - > fsp_name - > st . st_ex_size ) | |
( smb_maxcnt > ( fsp - > fsp_name - > st . st_ex_size - startpos ) ) ) {
/*
* We already know that we would do a short read , so don ' t
* try the sendfile ( ) path .
*/
goto nosendfile_read ;
}
2007-09-13 01:48:20 +04:00
/*
2002-09-25 19:19:00 +04:00
* Set up the packet header before send . We
* assume here the sendfile will work ( get the
* correct amount of data ) .
*/
2007-08-12 15:40:27 +04:00
header = data_blob_const ( headerbuf , sizeof ( headerbuf ) ) ;
2022-04-05 04:43:54 +03:00
construct_smb1_reply_common_req ( req , ( char * ) headerbuf ) ;
2016-06-13 19:20:43 +03:00
setup_readX_header ( ( char * ) headerbuf , smb_maxcnt ) ;
2002-09-25 19:19:00 +04:00
2014-05-22 01:23:34 +04:00
nread = SMB_VFS_SENDFILE ( xconn - > transport . sock , fsp , & header ,
2010-08-15 10:56:18 +04:00
startpos , smb_maxcnt ) ;
if ( nread = = - 1 ) {
2014-05-23 14:59:43 +04:00
saved_errno = errno ;
2009-01-13 22:19:11 +03:00
/* Returning ENOSYS means no data at all was sent.
2008-08-26 08:06:42 +04:00
Do this as a normal read . */
2009-01-13 22:19:11 +03:00
if ( errno = = ENOSYS ) {
2004-12-21 01:01:42 +03:00
goto normal_read ;
}
2002-09-25 19:19:00 +04:00
/*
2004-11-25 01:05:59 +03:00
* Special hack for broken Linux with no working sendfile . If we
* return EINTR we sent the header but not the rest of the data .
* Fake this up by doing read / write calls .
2002-09-25 19:19:00 +04:00
*/
2004-12-21 01:01:42 +03:00
2004-11-25 01:05:59 +03:00
if ( errno = = EINTR ) {
/* Ensure we don't do this again. */
2004-08-06 21:49:00 +04:00
set_use_sendfile ( SNUM ( conn ) , False ) ;
2004-11-25 01:05:59 +03:00
DEBUG ( 0 , ( " send_file_readX: sendfile not available. Faking.. \n " ) ) ;
2014-06-12 10:40:25 +04:00
nread = fake_sendfile ( xconn , fsp , startpos ,
2007-08-12 15:22:26 +04:00
smb_maxcnt ) ;
if ( nread = = - 1 ) {
2014-05-23 14:59:43 +04:00
saved_errno = errno ;
2009-07-11 01:50:37 +04:00
DEBUG ( 0 , ( " send_file_readX: "
" fake_sendfile failed for "
2014-05-23 14:59:43 +04:00
" file %s (%s) for client %s. "
" Terminating \n " ,
2009-07-11 01:50:37 +04:00
fsp_str_dbg ( fsp ) ,
2014-05-23 14:59:43 +04:00
smbXsrv_connection_dbg ( xconn ) ,
strerror ( saved_errno ) ) ) ;
errno = saved_errno ;
2006-12-18 07:25:21 +03:00
exit_server_cleanly ( " send_file_readX: fake_sendfile failed " ) ;
2004-11-25 01:05:59 +03:00
}
2012-06-14 15:10:33 +04:00
DEBUG ( 3 , ( " send_file_readX: fake_sendfile %s max=%d nread=%d \n " ,
fsp_fnum_dbg ( fsp ) , ( int ) smb_maxcnt , ( int ) nread ) ) ;
2007-08-12 13:16:54 +04:00
/* No outbuf here means successful sendfile. */
2017-07-09 15:21:21 +03:00
goto out ;
2004-08-06 21:49:00 +04:00
}
2002-09-25 19:19:00 +04:00
2009-07-11 01:50:37 +04:00
DEBUG ( 0 , ( " send_file_readX: sendfile failed for file "
" %s (%s). Terminating \n " , fsp_str_dbg ( fsp ) ,
strerror ( errno ) ) ) ;
2006-12-18 07:25:21 +03:00
exit_server_cleanly ( " send_file_readX sendfile failed " ) ;
2009-02-21 00:28:36 +03:00
} else if ( nread = = 0 ) {
/*
* Some sendfile implementations return 0 to indicate
* that there was a short read , but nothing was
* actually written to the socket . In this case ,
* fallback to the normal read path so the header gets
* the correct byte count .
*/
DEBUG ( 3 , ( " send_file_readX: sendfile sent zero bytes "
" falling back to the normal read: %s \n " ,
2009-07-11 01:50:37 +04:00
fsp_str_dbg ( fsp ) ) ) ;
2009-02-21 00:28:36 +03:00
goto normal_read ;
2002-09-25 19:19:00 +04:00
}
2012-06-14 15:10:33 +04:00
DEBUG ( 3 , ( " send_file_readX: sendfile %s max=%d nread=%d \n " ,
fsp_fnum_dbg ( fsp ) , ( int ) smb_maxcnt , ( int ) nread ) ) ;
2009-01-14 00:02:44 +03:00
/* Deal with possible short send. */
2009-01-14 02:36:09 +03:00
if ( nread ! = smb_maxcnt + sizeof ( headerbuf ) ) {
2014-06-12 10:42:16 +04:00
ssize_t ret ;
ret = sendfile_short_send ( xconn , fsp , nread ,
sizeof ( headerbuf ) , smb_maxcnt ) ;
if ( ret = = - 1 ) {
const char * r ;
r = " send_file_readX: sendfile_short_send failed " ;
DEBUG ( 0 , ( " %s for file %s (%s). \n " ,
r , fsp_str_dbg ( fsp ) , strerror ( errno ) ) ) ;
exit_server_cleanly ( r ) ;
}
2009-01-14 02:36:09 +03:00
}
2007-08-12 13:16:54 +04:00
/* No outbuf here means successful sendfile. */
2017-07-09 15:21:21 +03:00
goto out ;
2002-09-25 19:19:00 +04:00
}
2007-06-01 23:34:08 +04:00
normal_read :
2007-05-16 04:21:12 +04:00
2007-08-12 16:57:56 +04:00
if ( ( smb_maxcnt & 0xFF0000 ) > 0x10000 ) {
2015-04-27 02:02:55 +03:00
uint8_t headerbuf [ smb_size + 2 * 12 + 1 /* padding byte */ ] ;
2014-05-23 14:59:43 +04:00
ssize_t ret ;
2007-08-12 15:40:27 +04:00
2016-04-27 13:15:37 +03:00
if ( ! S_ISREG ( fsp - > fsp_name - > st . st_ex_mode ) | |
( startpos > fsp - > fsp_name - > st . st_ex_size ) | |
( smb_maxcnt > ( fsp - > fsp_name - > st . st_ex_size - startpos ) ) ) {
/*
* We already know that we would do a short
* read , so don ' t try the sendfile ( ) path .
*/
goto nosendfile_read ;
}
2022-04-05 04:43:54 +03:00
construct_smb1_reply_common_req ( req , ( char * ) headerbuf ) ;
2016-06-13 19:20:43 +03:00
setup_readX_header ( ( char * ) headerbuf , smb_maxcnt ) ;
2007-08-12 15:40:27 +04:00
2007-05-16 04:07:38 +04:00
/* Send out the header. */
2014-05-22 01:23:34 +04:00
ret = write_data ( xconn - > transport . sock , ( char * ) headerbuf ,
2014-05-23 14:59:43 +04:00
sizeof ( headerbuf ) ) ;
if ( ret ! = sizeof ( headerbuf ) ) {
saved_errno = errno ;
2010-08-15 18:02:37 +04:00
/*
* Try and give an error message saying what
* client failed .
*/
2009-07-11 01:50:37 +04:00
DEBUG ( 0 , ( " send_file_readX: write_data failed for file "
2014-05-23 14:59:43 +04:00
" %s (%s) for client %s. Terminating \n " ,
fsp_str_dbg ( fsp ) ,
smbXsrv_connection_dbg ( xconn ) ,
strerror ( saved_errno ) ) ) ;
errno = saved_errno ;
2007-05-16 04:07:38 +04:00
exit_server_cleanly ( " send_file_readX sendfile failed " ) ;
}
2014-06-12 10:40:25 +04:00
nread = fake_sendfile ( xconn , fsp , startpos , smb_maxcnt ) ;
2007-08-12 15:22:26 +04:00
if ( nread = = - 1 ) {
2014-05-23 14:59:43 +04:00
saved_errno = errno ;
DEBUG ( 0 , ( " send_file_readX: fake_sendfile failed for file "
" %s (%s) for client %s. Terminating \n " ,
fsp_str_dbg ( fsp ) ,
smbXsrv_connection_dbg ( xconn ) ,
strerror ( saved_errno ) ) ) ;
errno = saved_errno ;
2007-05-16 04:07:38 +04:00
exit_server_cleanly ( " send_file_readX: fake_sendfile failed " ) ;
}
2017-07-09 15:21:21 +03:00
goto out ;
2008-09-01 20:42:44 +04:00
}
2002-09-25 19:19:00 +04:00
2009-05-02 13:31:37 +04:00
nosendfile_read :
2022-04-05 05:53:20 +03:00
reply_smb1_outbuf ( req , 12 , smb_maxcnt + 1 /* padding byte */ ) ;
2012-02-26 19:49:09 +04:00
SSVAL ( req - > outbuf , smb_vwv0 , 0xff ) ; /* andx chain ends */
SSVAL ( req - > outbuf , smb_vwv1 , 0 ) ; /* no andx offset */
2002-09-25 19:19:00 +04:00
2014-08-15 09:04:33 +04:00
nread = read_file ( fsp , smb_buf ( req - > outbuf ) + 1 /* padding byte */ ,
startpos , smb_maxcnt ) ;
2009-07-11 05:23:00 +04:00
saved_errno = errno ;
2009-05-13 03:32:32 +04:00
2008-09-01 20:42:44 +04:00
if ( nread < 0 ) {
2009-07-11 05:23:00 +04:00
reply_nterror ( req , map_nt_error_from_unix ( saved_errno ) ) ;
2008-09-01 20:42:44 +04:00
return ;
}
2007-05-16 04:07:38 +04:00
2016-06-13 19:20:43 +03:00
setup_readX_header ( ( char * ) req - > outbuf , nread ) ;
2007-05-16 04:07:38 +04:00
2012-06-14 15:10:33 +04:00
DEBUG ( 3 , ( " send_file_readX %s max=%d nread=%d \n " ,
fsp_fnum_dbg ( fsp ) , ( int ) smb_maxcnt , ( int ) nread ) ) ;
2009-05-13 03:32:32 +04:00
return ;
2017-07-09 15:21:21 +03:00
out :
2009-05-13 03:32:32 +04:00
TALLOC_FREE ( req - > outbuf ) ;
return ;
2002-09-25 19:19:00 +04:00
}
1996-05-04 11:50:46 +04:00
2013-03-15 22:57:48 +04:00
/****************************************************************************
Work out how much space we have for a read return .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static size_t calc_max_read_pdu ( const struct smb_request * req )
{
2014-06-11 17:12:32 +04:00
struct smbXsrv_connection * xconn = req - > xconn ;
2014-05-21 12:56:26 +04:00
2014-06-11 17:12:32 +04:00
if ( xconn - > protocol < PROTOCOL_NT1 ) {
2014-05-21 12:56:26 +04:00
return xconn - > smb1 . sessions . max_send ;
2013-03-15 22:57:48 +04:00
}
if ( ! lp_large_readwrite ( ) ) {
2014-05-21 12:56:26 +04:00
return xconn - > smb1 . sessions . max_send ;
2013-03-15 22:57:48 +04:00
}
if ( req_is_in_chain ( req ) ) {
2014-05-21 12:56:26 +04:00
return xconn - > smb1 . sessions . max_send ;
2013-03-15 22:57:48 +04:00
}
if ( req - > encrypted ) {
/*
* Don ' t take encrypted traffic up to the
* limit . There are padding considerations
* that make that tricky .
*/
2014-05-21 12:56:26 +04:00
return xconn - > smb1 . sessions . max_send ;
2013-03-15 22:57:48 +04:00
}
2022-03-08 06:51:06 +03:00
if ( smb1_srv_is_signing_active ( xconn ) ) {
2013-03-15 22:57:48 +04:00
return 0x1FFFF ;
}
2022-01-22 01:49:11 +03:00
if ( ! lp_smb1_unix_extensions ( ) ) {
2013-03-15 22:57:48 +04:00
return 0x1FFFF ;
}
/*
* We can do ultra - large POSIX reads .
*/
return 0xFFFFFF ;
}
/****************************************************************************
Calculate how big a read can be . Copes with all clients . It ' s always
safe to return a short read - Windows does this .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static size_t calc_read_size ( const struct smb_request * req ,
size_t upper_size ,
size_t lower_size )
{
2014-06-11 17:12:32 +04:00
struct smbXsrv_connection * xconn = req - > xconn ;
2013-03-15 22:57:48 +04:00
size_t max_pdu = calc_max_read_pdu ( req ) ;
size_t total_size = 0 ;
size_t hdr_len = MIN_SMB_SIZE + VWV ( 12 ) ;
2014-08-15 09:04:33 +04:00
size_t max_len = max_pdu - hdr_len - 1 /* padding byte */ ;
2013-03-15 22:57:48 +04:00
/*
* Windows explicitly ignores upper size of 0xFFFF .
* See [ MS - SMB ] . pdf < 26 > Section 2.2 .4 .2 .1 :
* We must do the same as these will never fit even in
* an extended size NetBIOS packet .
*/
if ( upper_size = = 0xFFFF ) {
upper_size = 0 ;
}
2014-06-11 17:12:32 +04:00
if ( xconn - > protocol < PROTOCOL_NT1 ) {
2013-03-15 22:57:48 +04:00
upper_size = 0 ;
}
total_size = ( ( upper_size < < 16 ) | lower_size ) ;
/*
* LARGE_READX test shows it ' s always safe to return
* a short read . Windows does so .
*/
return MIN ( total_size , max_len ) ;
}
1996-05-04 11:50:46 +04:00
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a read and X .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2008-01-05 02:37:24 +03:00
void reply_read_and_X ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
2007-08-11 01:33:58 +04:00
files_struct * fsp ;
2012-04-05 08:53:08 +04:00
off_t startpos ;
2007-08-11 01:33:58 +04:00
size_t smb_maxcnt ;
2013-01-23 21:57:50 +04:00
size_t upper_size ;
2007-10-19 04:40:25 +04:00
bool big_readX = False ;
2002-09-25 19:19:00 +04:00
#if 0
2008-11-02 14:20:47 +03:00
size_t smb_mincnt = SVAL ( req - > vwv + 6 , 0 ) ;
2002-09-25 19:19:00 +04:00
# endif
1996-05-04 11:50:46 +04:00
2002-09-25 19:19:00 +04:00
START_PROFILE ( SMBreadX ) ;
1998-03-12 02:20:26 +03:00
2007-08-11 14:40:35 +04:00
if ( ( req - > wct ! = 10 ) & & ( req - > wct ! = 12 ) ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
return ;
2007-08-11 01:33:58 +04:00
}
2008-11-02 14:20:47 +03:00
fsp = file_fsp ( req , SVAL ( req - > vwv + 2 , 0 ) ) ;
startpos = IVAL_TO_SMB_OFF_T ( req - > vwv + 3 , 0 ) ;
smb_maxcnt = SVAL ( req - > vwv + 5 , 0 ) ;
2007-08-11 14:40:35 +04:00
2002-09-25 19:19:00 +04:00
/* If it's an IPC, pass off the pipe handler. */
if ( IS_IPC ( conn ) ) {
2007-08-11 14:53:36 +04:00
reply_pipe_read_and_X ( req ) ;
2002-09-25 19:19:00 +04:00
END_PROFILE ( SMBreadX ) ;
2007-08-11 14:40:35 +04:00
return ;
2002-09-25 19:19:00 +04:00
}
2008-06-19 18:31:59 +04:00
if ( ! check_fsp ( conn , req , fsp ) ) {
2007-08-11 14:40:35 +04:00
END_PROFILE ( SMBreadX ) ;
return ;
}
2008-11-06 22:16:04 +03:00
if ( ! CHECK_READ ( fsp , req ) ) {
2009-12-19 01:25:39 +03:00
reply_nterror ( req , NT_STATUS_ACCESS_DENIED ) ;
2007-08-11 14:40:35 +04:00
END_PROFILE ( SMBreadX ) ;
return ;
2005-07-08 08:51:27 +04:00
}
1996-05-04 11:50:46 +04:00
2013-01-23 21:57:50 +04:00
upper_size = SVAL ( req - > vwv + 7 , 0 ) ;
2013-03-15 22:57:48 +04:00
smb_maxcnt = calc_read_size ( req , upper_size , smb_maxcnt ) ;
if ( smb_maxcnt > ( 0x1FFFF - ( MIN_SMB_SIZE + VWV ( 12 ) ) ) ) {
/*
* This is a heuristic to avoid keeping large
* outgoing buffers around over long - lived aio
* requests .
*/
big_readX = True ;
2004-11-24 06:42:01 +03:00
}
2007-08-11 15:20:21 +04:00
if ( req - > wct = = 12 ) {
2002-09-25 19:19:00 +04:00
/*
* This is a large offset ( 64 bit ) read .
*/
2012-04-05 08:53:08 +04:00
startpos | = ( ( ( off_t ) IVAL ( req - > vwv + 10 , 0 ) ) < < 32 ) ;
1999-12-13 16:27:58 +03:00
2002-09-25 19:19:00 +04:00
}
1999-12-13 16:27:58 +03:00
2010-04-06 01:16:21 +04:00
if ( ! big_readX ) {
NTSTATUS status = schedule_aio_read_and_X ( conn ,
req ,
fsp ,
startpos ,
smb_maxcnt ) ;
if ( NT_STATUS_IS_OK ( status ) ) {
/* Read scheduled - we're done. */
goto out ;
}
if ( ! NT_STATUS_EQUAL ( status , NT_STATUS_RETRY ) ) {
/* Real error - report to client. */
END_PROFILE ( SMBreadX ) ;
reply_nterror ( req , status ) ;
return ;
}
/* NT_STATUS_RETRY - fall back to sync read. */
2007-08-11 15:20:21 +04:00
}
2014-06-12 10:43:26 +04:00
smbd_lock_socket ( req - > xconn ) ;
2007-08-12 13:16:54 +04:00
send_file_readX ( conn , req , fsp , startpos , smb_maxcnt ) ;
2014-06-12 10:43:26 +04:00
smbd_unlock_socket ( req - > xconn ) ;
2007-08-11 14:40:35 +04:00
2009-05-13 03:32:32 +04:00
out :
2007-08-11 14:40:35 +04:00
END_PROFILE ( SMBreadX ) ;
return ;
2007-08-11 14:26:40 +04:00
}
2007-08-15 05:54:37 +04:00
/****************************************************************************
Error replies to writebraw must have smb_wct = = 1. Fix this up .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void error_to_writebrawerr ( struct smb_request * req )
{
2015-04-27 02:02:55 +03:00
uint8_t * old_outbuf = req - > outbuf ;
2007-08-15 05:54:37 +04:00
2022-04-05 05:53:20 +03:00
reply_smb1_outbuf ( req , 1 , 0 ) ;
2007-08-15 05:54:37 +04:00
memcpy ( req - > outbuf , old_outbuf , smb_size ) ;
TALLOC_FREE ( old_outbuf ) ;
}
2010-08-15 17:45:21 +04:00
/****************************************************************************
Read 4 bytes of a smb packet and return the smb length of the packet .
Store the result in the buffer . This version of the function will
never return a session keepalive ( length of zero ) .
Timeout is in milliseconds .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static NTSTATUS read_smb_length ( int fd , char * inbuf , unsigned int timeout ,
size_t * len )
{
2011-07-12 10:55:58 +04:00
uint8_t msgtype = NBSSkeepalive ;
2010-08-15 17:45:21 +04:00
2011-07-12 10:55:58 +04:00
while ( msgtype = = NBSSkeepalive ) {
2010-08-15 17:45:21 +04:00
NTSTATUS status ;
status = read_smb_length_return_keepalive ( fd , inbuf , timeout ,
len ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2010-08-15 17:46:29 +04:00
char addr [ INET6_ADDRSTRLEN ] ;
/* Try and give an error message
* saying what client failed . */
2019-05-09 01:32:41 +03:00
DEBUG ( 0 , ( " read_smb_length_return_keepalive failed for "
2010-08-15 17:46:29 +04:00
" client %s read error = %s. \n " ,
get_peer_addr ( fd , addr , sizeof ( addr ) ) ,
nt_errstr ( status ) ) ) ;
2010-08-15 17:45:21 +04:00
return status ;
}
msgtype = CVAL ( inbuf , 0 ) ;
}
DEBUG ( 10 , ( " read_smb_length: got smb length of %lu \n " ,
( unsigned long ) len ) ) ;
return NT_STATUS_OK ;
}
1996-05-04 11:50:46 +04:00
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a writebraw ( core + or LANMAN1 .0 protocol ) .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
2008-01-05 02:37:24 +03:00
void reply_writebraw ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
2014-06-11 17:12:32 +04:00
struct smbXsrv_connection * xconn = req - > xconn ;
2007-08-15 05:54:37 +04:00
char * buf = NULL ;
2001-09-04 23:10:30 +04:00
ssize_t nwritten = 0 ;
ssize_t total_written = 0 ;
size_t numtowrite = 0 ;
size_t tcount ;
2012-04-05 08:53:08 +04:00
off_t startpos ;
2011-05-05 21:41:59 +04:00
const char * data = NULL ;
2007-10-19 04:40:25 +04:00
bool write_through ;
2007-08-15 05:54:37 +04:00
files_struct * fsp ;
2009-03-14 00:15:28 +03:00
struct lock_struct lock ;
2007-06-15 23:24:04 +04:00
NTSTATUS status ;
2007-08-15 05:54:37 +04:00
2001-09-04 23:10:30 +04:00
START_PROFILE ( SMBwritebraw ) ;
1996-05-04 11:50:46 +04:00
2007-08-15 05:54:37 +04:00
/*
* If we ever reply with an error , it must have the SMB command
* type of SMBwritec , not SMBwriteBraw , as this tells the client
* we ' re finished .
*/
2011-05-05 21:41:59 +04:00
SCVAL ( discard_const_p ( uint8_t , req - > inbuf ) , smb_com , SMBwritec ) ;
2007-08-15 05:54:37 +04:00
2022-03-08 06:51:06 +03:00
if ( smb1_srv_is_signing_active ( xconn ) ) {
2007-08-15 05:54:37 +04:00
END_PROFILE ( SMBwritebraw ) ;
exit_server_cleanly ( " reply_writebraw: SMB signing is active - "
" raw reads/writes are disallowed. " ) ;
}
if ( req - > wct < 12 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
error_to_writebrawerr ( req ) ;
END_PROFILE ( SMBwritebraw ) ;
return ;
}
2014-05-23 11:26:26 +04:00
if ( xconn - > smb1 . echo_handler . trusted_fde ) {
2010-05-26 19:52:10 +04:00
DEBUG ( 2 , ( " SMBwritebraw rejected with NOT_SUPPORTED because of "
" 'async smb echo handler = yes' \n " ) ) ;
2010-03-22 11:11:05 +03:00
reply_nterror ( req , NT_STATUS_NOT_SUPPORTED ) ;
error_to_writebrawerr ( req ) ;
END_PROFILE ( SMBwritebraw ) ;
return ;
}
2008-11-02 14:20:47 +03:00
fsp = file_fsp ( req , SVAL ( req - > vwv + 0 , 0 ) ) ;
2008-06-19 18:31:59 +04:00
if ( ! check_fsp ( conn , req , fsp ) ) {
2007-08-15 05:54:37 +04:00
error_to_writebrawerr ( req ) ;
END_PROFILE ( SMBwritebraw ) ;
return ;
2003-07-17 04:53:37 +04:00
}
2005-07-08 08:51:27 +04:00
if ( ! CHECK_WRITE ( fsp ) ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_ACCESS_DENIED ) ;
2007-08-15 05:54:37 +04:00
error_to_writebrawerr ( req ) ;
END_PROFILE ( SMBwritebraw ) ;
return ;
2005-07-08 08:51:27 +04:00
}
2007-08-15 05:54:37 +04:00
2008-11-02 14:20:47 +03:00
tcount = IVAL ( req - > vwv + 1 , 0 ) ;
startpos = IVAL_TO_SMB_OFF_T ( req - > vwv + 3 , 0 ) ;
write_through = BITSETW ( req - > vwv + 7 , 0 ) ;
1996-05-04 11:50:46 +04:00
2001-09-04 23:10:30 +04:00
/* We have to deal with slightly different formats depending
on whether we are using the core + or lanman1 .0 protocol */
1996-05-04 11:50:46 +04:00
2023-05-25 08:50:43 +03:00
if ( xconn - > protocol < = PROTOCOL_COREPLUS ) {
2011-05-05 21:41:59 +04:00
numtowrite = SVAL ( smb_buf_const ( req - > inbuf ) , - 2 ) ;
data = smb_buf_const ( req - > inbuf ) ;
2001-09-04 23:10:30 +04:00
} else {
2008-11-02 14:20:47 +03:00
numtowrite = SVAL ( req - > vwv + 10 , 0 ) ;
data = smb_base ( req - > inbuf ) + SVAL ( req - > vwv + 11 , 0 ) ;
2001-09-04 23:10:30 +04:00
}
1996-05-04 11:50:46 +04:00
2007-08-15 05:54:37 +04:00
/* Ensure we don't write bytes past the end of this packet. */
2017-09-08 20:13:14 +03:00
/*
* This already protects us against CVE - 2017 - 12163.
*/
2007-08-15 05:54:37 +04:00
if ( data + numtowrite > smb_base ( req - > inbuf ) + smb_len ( req - > inbuf ) ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
error_to_writebrawerr ( req ) ;
END_PROFILE ( SMBwritebraw ) ;
return ;
}
1996-05-04 11:50:46 +04:00
2010-04-29 03:42:04 +04:00
if ( ! fsp - > print_file ) {
2021-11-17 02:00:03 +03:00
init_strict_lock_struct ( fsp ,
( uint64_t ) req - > smbpid ,
( uint64_t ) startpos ,
( uint64_t ) tcount ,
WRITE_LOCK ,
lp_posix_cifsu_locktype ( fsp ) ,
& lock ) ;
2009-03-14 00:15:28 +03:00
2017-07-09 15:34:10 +03:00
if ( ! SMB_VFS_STRICT_LOCK_CHECK ( conn , fsp , & lock ) ) {
2010-03-24 22:47:01 +03:00
reply_nterror ( req , NT_STATUS_FILE_LOCK_CONFLICT ) ;
error_to_writebrawerr ( req ) ;
END_PROFILE ( SMBwritebraw ) ;
return ;
}
2001-09-04 23:10:30 +04:00
}
2007-08-15 05:54:37 +04:00
if ( numtowrite > 0 ) {
2007-10-31 02:22:24 +03:00
nwritten = write_file ( req , fsp , data , startpos , numtowrite ) ;
2007-08-15 05:54:37 +04:00
}
2012-06-14 15:10:33 +04:00
DEBUG ( 3 , ( " reply_writebraw: initial write %s start=%.0f num=%d "
2007-08-15 05:54:37 +04:00
" wrote=%d sync=%d \n " ,
2012-06-14 15:10:33 +04:00
fsp_fnum_dbg ( fsp ) , ( double ) startpos , ( int ) numtowrite ,
2007-08-15 05:54:37 +04:00
( int ) nwritten , ( int ) write_through ) ) ;
1996-05-04 11:50:46 +04:00
2002-12-31 13:25:11 +03:00
if ( nwritten < ( ssize_t ) numtowrite ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_DISK_FULL ) ;
2007-08-15 05:54:37 +04:00
error_to_writebrawerr ( req ) ;
2017-07-09 15:21:21 +03:00
goto out ;
2001-09-04 23:10:30 +04:00
}
1996-05-04 11:50:46 +04:00
2001-09-04 23:10:30 +04:00
total_written = nwritten ;
1996-05-04 11:50:46 +04:00
2007-08-15 05:54:37 +04:00
/* Allocate a buffer of 64k + length. */
2011-06-07 05:30:12 +04:00
buf = talloc_array ( NULL , char , 65540 ) ;
2007-08-15 05:54:37 +04:00
if ( ! buf ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
2007-08-15 05:54:37 +04:00
error_to_writebrawerr ( req ) ;
2017-07-09 15:21:21 +03:00
goto out ;
2007-08-15 05:54:37 +04:00
}
/* Return a SMBwritebraw message to the redirector to tell
* it to send more bytes */
memcpy ( buf , req - > inbuf , smb_size ) ;
2023-05-25 08:50:43 +03:00
srv_smb1_set_message ( buf , xconn - > protocol > PROTOCOL_COREPLUS ? 1 : 0 , 0 , True ) ;
2007-08-15 05:54:37 +04:00
SCVAL ( buf , smb_com , SMBwritebraw ) ;
SSVALS ( buf , smb_vwv0 , 0xFFFF ) ;
show_msg ( buf ) ;
2022-03-31 22:09:13 +03:00
if ( ! smb1_srv_send ( req - > xconn ,
2023-06-05 16:45:35 +03:00
buf ,
false ,
0 , /* no signing */
IS_CONN_ENCRYPTED ( conn ) ) ) {
2022-03-31 22:09:13 +03:00
exit_server_cleanly ( " reply_writebraw: smb1_srv_send "
2007-08-15 05:54:37 +04:00
" failed. " ) ;
}
2001-09-04 23:10:30 +04:00
/* Now read the raw data into the buffer and write it */
2014-05-22 01:23:34 +04:00
status = read_smb_length ( xconn - > transport . sock , buf , SMB_SECONDARY_WAIT ,
2008-01-25 23:31:40 +03:00
& numtowrite ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2006-12-18 07:25:21 +03:00
exit_server_cleanly ( " secondary writebraw failed " ) ;
2001-09-04 23:10:30 +04:00
}
1996-05-04 11:50:46 +04:00
2007-08-15 05:54:37 +04:00
/* Set up outbuf to return the correct size */
2022-04-05 05:53:20 +03:00
reply_smb1_outbuf ( req , 1 , 0 ) ;
1996-05-04 11:50:46 +04:00
2001-09-04 23:10:30 +04:00
if ( numtowrite ! = 0 ) {
1996-05-04 11:50:46 +04:00
2007-08-15 05:54:37 +04:00
if ( numtowrite > 0xFFFF ) {
DEBUG ( 0 , ( " reply_writebraw: Oversize secondary write "
" raw requested (%u). Terminating \n " ,
2001-09-04 23:10:30 +04:00
( unsigned int ) numtowrite ) ) ;
2006-12-18 07:25:21 +03:00
exit_server_cleanly ( " secondary writebraw failed " ) ;
2001-09-04 23:10:30 +04:00
}
1996-05-04 11:50:46 +04:00
2001-09-04 23:10:30 +04:00
if ( tcount > nwritten + numtowrite ) {
2007-08-15 05:54:37 +04:00
DEBUG ( 3 , ( " reply_writebraw: Client overestimated the "
" write %d %d %d \n " ,
2001-09-04 23:10:30 +04:00
( int ) tcount , ( int ) nwritten , ( int ) numtowrite ) ) ;
}
1996-05-04 11:50:46 +04:00
2014-11-19 17:06:49 +03:00
status = read_data_ntstatus ( xconn - > transport . sock , buf + 4 ,
numtowrite ) ;
2008-01-26 12:39:21 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2010-08-15 17:30:21 +04:00
/* Try and give an error message
* saying what client failed . */
DEBUG ( 0 , ( " reply_writebraw: Oversize secondary write "
" raw read failed (%s) for client %s. "
" Terminating \n " , nt_errstr ( status ) ,
2014-05-23 14:59:43 +04:00
smbXsrv_connection_dbg ( xconn ) ) ) ;
2006-12-18 07:25:21 +03:00
exit_server_cleanly ( " secondary writebraw failed " ) ;
2001-09-04 23:10:30 +04:00
}
1996-05-04 11:50:46 +04:00
2017-09-08 20:13:14 +03:00
/*
* We are not vulnerable to CVE - 2017 - 12163
2019-05-27 12:48:13 +03:00
* here as we are guaranteed to have numtowrite
2017-09-08 20:13:14 +03:00
* bytes available - we just read from the client .
*/
2010-03-26 19:32:40 +03:00
nwritten = write_file ( req , fsp , buf + 4 , startpos + nwritten , numtowrite ) ;
2006-07-25 04:16:45 +04:00
if ( nwritten = = - 1 ) {
2007-08-15 05:54:37 +04:00
TALLOC_FREE ( buf ) ;
2009-07-11 05:23:00 +04:00
reply_nterror ( req , map_nt_error_from_unix ( errno ) ) ;
2007-08-15 05:54:37 +04:00
error_to_writebrawerr ( req ) ;
2017-07-09 15:21:21 +03:00
goto out ;
2006-07-25 04:16:45 +04:00
}
1996-05-04 11:50:46 +04:00
2001-09-04 23:10:30 +04:00
if ( nwritten < ( ssize_t ) numtowrite ) {
2007-08-15 05:54:37 +04:00
SCVAL ( req - > outbuf , smb_rcls , ERRHRD ) ;
SSVAL ( req - > outbuf , smb_err , ERRdiskfull ) ;
2001-09-04 23:10:30 +04:00
}
2007-08-15 05:54:37 +04:00
if ( nwritten > 0 ) {
2001-09-04 23:10:30 +04:00
total_written + = nwritten ;
2007-08-15 05:54:37 +04:00
}
2001-09-04 23:10:30 +04:00
}
2007-08-15 05:54:37 +04:00
TALLOC_FREE ( buf ) ;
SSVAL ( req - > outbuf , smb_vwv0 , total_written ) ;
2005-07-10 20:37:32 +04:00
2007-06-15 23:24:04 +04:00
status = sync_file ( conn , fsp , write_through ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 5 , ( " reply_writebraw: sync_file for %s returned %s \n " ,
2009-07-11 01:50:37 +04:00
fsp_str_dbg ( fsp ) , nt_errstr ( status ) ) ) ;
2007-08-15 05:54:37 +04:00
reply_nterror ( req , status ) ;
error_to_writebrawerr ( req ) ;
2017-07-09 15:21:21 +03:00
goto out ;
2007-06-15 23:24:04 +04:00
}
2001-09-04 23:10:30 +04:00
2023-08-02 00:44:40 +03:00
DEBUG ( 3 , ( " reply_writebraw: secondary write %s start=%.0f num=%d "
2007-08-15 05:54:37 +04:00
" wrote=%d \n " ,
2012-06-14 15:10:33 +04:00
fsp_fnum_dbg ( fsp ) , ( double ) startpos , ( int ) numtowrite ,
2007-08-15 05:54:37 +04:00
( int ) total_written ) ) ;
2001-09-04 23:10:30 +04:00
2007-08-15 05:54:37 +04:00
/* We won't return a status if write through is not selected - this
* follows what WfWg does */
2001-09-04 23:10:30 +04:00
END_PROFILE ( SMBwritebraw ) ;
2007-08-15 05:54:37 +04:00
2001-09-04 23:10:30 +04:00
if ( ! write_through & & total_written = = tcount ) {
2002-04-11 06:20:56 +04:00
# if RABBIT_PELLET_FIX
2001-09-04 23:10:30 +04:00
/*
* Fix for " rabbit pellet " mode , trigger an early TCP ack by
2011-07-12 10:55:58 +04:00
* sending a NBSSkeepalive . Thanks to DaveCB at Sun for this .
2007-08-15 05:54:37 +04:00
* JRA .
2001-09-04 23:10:30 +04:00
*/
2014-05-22 01:23:34 +04:00
if ( ! send_keepalive ( xconn - > transport . sock ) ) {
2007-08-15 05:54:37 +04:00
exit_server_cleanly ( " reply_writebraw: send of "
" keepalive failed " ) ;
}
2002-04-11 06:20:56 +04:00
# endif
2007-08-15 05:54:37 +04:00
TALLOC_FREE ( req - > outbuf ) ;
2001-09-04 23:10:30 +04:00
}
2007-08-15 05:54:37 +04:00
return ;
2009-03-14 00:15:28 +03:00
2017-07-09 15:21:21 +03:00
out :
2009-03-14 00:15:28 +03:00
END_PROFILE ( SMBwritebraw ) ;
return ;
1996-05-04 11:50:46 +04:00
}
2005-04-27 22:32:37 +04:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_LOCKING
1996-05-04 11:50:46 +04:00
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a writeunlock ( core + ) .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
2008-01-05 02:37:24 +03:00
void reply_writeunlock ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
2001-08-27 12:19:43 +04:00
ssize_t nwritten = - 1 ;
size_t numtowrite ;
2017-09-08 20:13:14 +03:00
size_t remaining ;
2012-04-05 08:53:08 +04:00
off_t startpos ;
2008-11-01 19:35:48 +03:00
const char * data ;
2003-10-10 01:04:48 +04:00
NTSTATUS status = NT_STATUS_OK ;
2007-08-15 00:20:51 +04:00
files_struct * fsp ;
2009-03-14 00:15:28 +03:00
struct lock_struct lock ;
2009-07-11 05:23:00 +04:00
int saved_errno = 0 ;
2007-08-15 00:20:51 +04:00
2001-08-27 12:19:43 +04:00
START_PROFILE ( SMBwriteunlock ) ;
2007-08-15 00:20:51 +04:00
if ( req - > wct < 5 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBwriteunlock ) ;
return ;
}
2008-10-19 17:30:12 +04:00
2008-11-02 14:20:47 +03:00
fsp = file_fsp ( req , SVAL ( req - > vwv + 0 , 0 ) ) ;
2007-08-15 00:20:51 +04:00
2008-06-19 18:31:59 +04:00
if ( ! check_fsp ( conn , req , fsp ) ) {
2007-08-15 00:20:51 +04:00
END_PROFILE ( SMBwriteunlock ) ;
return ;
}
2005-07-08 08:51:27 +04:00
if ( ! CHECK_WRITE ( fsp ) ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_ACCESS_DENIED ) ;
2007-08-15 00:20:51 +04:00
END_PROFILE ( SMBwriteunlock ) ;
return ;
2005-07-08 08:51:27 +04:00
}
1996-05-04 11:50:46 +04:00
2008-11-02 14:20:47 +03:00
numtowrite = SVAL ( req - > vwv + 1 , 0 ) ;
startpos = IVAL_TO_SMB_OFF_T ( req - > vwv + 2 , 0 ) ;
2008-11-01 19:35:48 +03:00
data = ( const char * ) req - > buf + 3 ;
2008-10-19 17:30:12 +04:00
2017-09-08 20:13:14 +03:00
/*
* Ensure client isn ' t asking us to write more than
* they sent . CVE - 2017 - 12163.
*/
remaining = smbreq_bufrem ( req , data ) ;
if ( numtowrite > remaining ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBwriteunlock ) ;
return ;
}
2010-04-29 03:42:04 +04:00
if ( ! fsp - > print_file & & numtowrite > 0 ) {
2021-11-17 02:00:03 +03:00
init_strict_lock_struct ( fsp ,
( uint64_t ) req - > smbpid ,
( uint64_t ) startpos ,
( uint64_t ) numtowrite ,
WRITE_LOCK ,
lp_posix_cifsu_locktype ( fsp ) ,
& lock ) ;
2009-03-14 00:15:28 +03:00
2017-07-09 15:34:10 +03:00
if ( ! SMB_VFS_STRICT_LOCK_CHECK ( conn , fsp , & lock ) ) {
2009-12-19 01:25:39 +03:00
reply_nterror ( req , NT_STATUS_FILE_LOCK_CONFLICT ) ;
2009-03-14 00:15:28 +03:00
END_PROFILE ( SMBwriteunlock ) ;
return ;
}
2001-08-27 12:19:43 +04:00
}
2001-08-07 05:19:32 +04:00
2001-08-27 12:19:43 +04:00
/* The special X/Open SMB protocol handling of
zero length writes is * NOT * done for
this call */
2005-07-08 08:51:27 +04:00
if ( numtowrite = = 0 ) {
2001-08-27 12:19:43 +04:00
nwritten = 0 ;
2005-07-08 08:51:27 +04:00
} else {
2007-10-31 02:22:24 +03:00
nwritten = write_file ( req , fsp , data , startpos , numtowrite ) ;
2009-07-11 05:23:00 +04:00
saved_errno = errno ;
2005-07-08 08:51:27 +04:00
}
2008-10-19 17:30:12 +04:00
2007-06-15 23:24:04 +04:00
status = sync_file ( conn , fsp , False /* write through */ ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 5 , ( " reply_writeunlock: sync_file for %s returned %s \n " ,
2009-07-11 01:50:37 +04:00
fsp_str_dbg ( fsp ) , nt_errstr ( status ) ) ) ;
2007-08-15 00:20:51 +04:00
reply_nterror ( req , status ) ;
2017-07-09 15:21:21 +03:00
goto out ;
2007-06-15 23:24:04 +04:00
}
2001-08-27 12:19:43 +04:00
2009-07-11 05:23:00 +04:00
if ( nwritten < 0 ) {
reply_nterror ( req , map_nt_error_from_unix ( saved_errno ) ) ;
2017-07-09 15:21:21 +03:00
goto out ;
2009-07-11 05:23:00 +04:00
}
if ( ( nwritten < numtowrite ) & & ( numtowrite ! = 0 ) ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_DISK_FULL ) ;
2017-07-09 15:21:21 +03:00
goto out ;
2001-08-07 05:19:32 +04:00
}
2010-03-24 22:47:01 +03:00
if ( numtowrite & & ! fsp - > print_file ) {
2019-06-14 14:48:58 +03:00
struct smbd_lock_element l = {
2019-08-08 20:26:28 +03:00
. req_guid = smbd_request_guid ( req , 0 ) ,
2019-06-14 14:48:58 +03:00
. smblctx = req - > smbpid ,
. brltype = UNLOCK_LOCK ,
2021-11-17 01:26:44 +03:00
. lock_flav = WINDOWS_LOCK ,
2019-06-14 14:48:58 +03:00
. offset = startpos ,
. count = numtowrite ,
} ;
2021-11-17 04:04:02 +03:00
status = smbd_do_unlocking ( req , fsp , 1 , & l ) ;
2003-10-10 01:04:48 +04:00
if ( NT_STATUS_V ( status ) ) {
2007-08-15 00:20:51 +04:00
reply_nterror ( req , status ) ;
2017-07-09 15:21:21 +03:00
goto out ;
2003-10-10 01:04:48 +04:00
}
2001-08-27 12:19:43 +04:00
}
2007-08-15 00:20:51 +04:00
2022-04-05 05:53:20 +03:00
reply_smb1_outbuf ( req , 1 , 0 ) ;
2008-10-19 17:30:12 +04:00
2007-08-15 00:20:51 +04:00
SSVAL ( req - > outbuf , smb_vwv0 , nwritten ) ;
2008-10-19 17:30:12 +04:00
2012-06-14 15:10:33 +04:00
DEBUG ( 3 , ( " writeunlock %s num=%d wrote=%d \n " ,
fsp_fnum_dbg ( fsp ) , ( int ) numtowrite , ( int ) nwritten ) ) ;
2008-10-19 17:30:12 +04:00
2017-07-09 15:21:21 +03:00
out :
2001-08-27 12:19:43 +04:00
END_PROFILE ( SMBwriteunlock ) ;
2007-08-15 00:20:51 +04:00
return ;
2001-08-07 05:19:32 +04:00
}
2005-04-27 22:32:37 +04:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_ALL
2001-08-07 05:19:32 +04:00
/****************************************************************************
Reply to a write .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-01-05 02:37:24 +03:00
void reply_write ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
2001-11-25 05:23:22 +03:00
size_t numtowrite ;
2017-09-08 20:13:14 +03:00
size_t remaining ;
2001-11-25 05:23:22 +03:00
ssize_t nwritten = - 1 ;
2012-04-05 08:53:08 +04:00
off_t startpos ;
2008-11-01 19:35:48 +03:00
const char * data ;
2007-08-14 22:16:04 +04:00
files_struct * fsp ;
2009-03-14 00:15:28 +03:00
struct lock_struct lock ;
2007-06-15 23:24:04 +04:00
NTSTATUS status ;
2009-07-11 05:23:00 +04:00
int saved_errno = 0 ;
2007-08-14 22:16:04 +04:00
2001-11-25 05:23:22 +03:00
START_PROFILE ( SMBwrite ) ;
1996-05-04 11:50:46 +04:00
2007-08-14 22:16:04 +04:00
if ( req - > wct < 5 ) {
END_PROFILE ( SMBwrite ) ;
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
return ;
}
2001-11-25 05:23:22 +03:00
/* If it's an IPC, pass off the pipe handler. */
if ( IS_IPC ( conn ) ) {
2007-08-14 22:16:04 +04:00
reply_pipe_write ( req ) ;
2001-11-25 05:23:22 +03:00
END_PROFILE ( SMBwrite ) ;
2007-08-14 22:16:04 +04:00
return ;
}
2008-11-02 14:20:47 +03:00
fsp = file_fsp ( req , SVAL ( req - > vwv + 0 , 0 ) ) ;
2007-08-14 22:16:04 +04:00
2008-06-19 18:31:59 +04:00
if ( ! check_fsp ( conn , req , fsp ) ) {
2007-08-15 05:54:37 +04:00
END_PROFILE ( SMBwrite ) ;
2007-08-14 22:16:04 +04:00
return ;
2001-11-25 05:23:22 +03:00
}
1999-11-16 01:11:10 +03:00
2005-07-08 08:51:27 +04:00
if ( ! CHECK_WRITE ( fsp ) ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_ACCESS_DENIED ) ;
2007-06-15 23:24:04 +04:00
END_PROFILE ( SMBwrite ) ;
2007-08-14 22:16:04 +04:00
return ;
2005-07-08 08:51:27 +04:00
}
1996-05-04 11:50:46 +04:00
2008-11-02 14:20:47 +03:00
numtowrite = SVAL ( req - > vwv + 1 , 0 ) ;
startpos = IVAL_TO_SMB_OFF_T ( req - > vwv + 2 , 0 ) ;
2008-11-01 19:35:48 +03:00
data = ( const char * ) req - > buf + 3 ;
2008-10-19 17:30:12 +04:00
2017-09-08 20:13:14 +03:00
/*
* Ensure client isn ' t asking us to write more than
* they sent . CVE - 2017 - 12163.
*/
remaining = smbreq_bufrem ( req , data ) ;
if ( numtowrite > remaining ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBwrite ) ;
return ;
}
2010-04-29 03:42:04 +04:00
if ( ! fsp - > print_file ) {
2021-11-17 02:00:03 +03:00
init_strict_lock_struct ( fsp ,
( uint64_t ) req - > smbpid ,
( uint64_t ) startpos ,
( uint64_t ) numtowrite ,
WRITE_LOCK ,
lp_posix_cifsu_locktype ( fsp ) ,
& lock ) ;
2009-03-14 00:15:28 +03:00
2017-07-09 15:34:10 +03:00
if ( ! SMB_VFS_STRICT_LOCK_CHECK ( conn , fsp , & lock ) ) {
2010-03-24 22:47:01 +03:00
reply_nterror ( req , NT_STATUS_FILE_LOCK_CONFLICT ) ;
END_PROFILE ( SMBwrite ) ;
return ;
}
2001-11-25 05:23:22 +03:00
}
1996-05-04 11:50:46 +04:00
2001-11-25 05:23:22 +03:00
/*
* X / Open SMB protocol says that if smb_vwv1 is
* zero then the file size should be extended or
* truncated to the size given in smb_vwv [ 2 - 3 ] .
*/
if ( numtowrite = = 0 ) {
/*
* This is actually an allocate call , and set EOF . JRA .
*/
2012-04-05 08:53:08 +04:00
nwritten = vfs_allocate_file_space ( fsp , ( off_t ) startpos ) ;
2001-11-25 05:23:22 +03:00
if ( nwritten < 0 ) {
2007-08-14 22:16:04 +04:00
reply_nterror ( req , NT_STATUS_DISK_FULL ) ;
2017-07-09 15:21:21 +03:00
goto out ;
2001-11-25 05:23:22 +03:00
}
2012-04-05 08:53:08 +04:00
nwritten = vfs_set_filelen ( fsp , ( off_t ) startpos ) ;
2001-11-25 05:23:22 +03:00
if ( nwritten < 0 ) {
2007-08-14 22:16:04 +04:00
reply_nterror ( req , NT_STATUS_DISK_FULL ) ;
2017-07-09 15:21:21 +03:00
goto out ;
2001-11-25 05:23:22 +03:00
}
2008-09-06 06:00:48 +04:00
trigger_write_time_update_immediate ( fsp ) ;
} else {
2007-10-31 02:22:24 +03:00
nwritten = write_file ( req , fsp , data , startpos , numtowrite ) ;
2008-09-06 06:00:48 +04:00
}
2007-06-15 23:24:04 +04:00
status = sync_file ( conn , fsp , False ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 5 , ( " reply_write: sync_file for %s returned %s \n " ,
2009-07-11 01:50:37 +04:00
fsp_str_dbg ( fsp ) , nt_errstr ( status ) ) ) ;
2007-08-14 22:16:04 +04:00
reply_nterror ( req , status ) ;
2017-07-09 15:21:21 +03:00
goto out ;
2007-06-15 23:24:04 +04:00
}
1996-05-04 11:50:46 +04:00
2009-07-11 05:23:00 +04:00
if ( nwritten < 0 ) {
reply_nterror ( req , map_nt_error_from_unix ( saved_errno ) ) ;
2017-07-09 15:21:21 +03:00
goto out ;
2009-07-11 05:23:00 +04:00
}
if ( ( nwritten = = 0 ) & & ( numtowrite ! = 0 ) ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_DISK_FULL ) ;
2017-07-09 15:21:21 +03:00
goto out ;
2001-11-25 05:23:22 +03:00
}
1996-05-04 11:50:46 +04:00
2022-04-05 05:53:20 +03:00
reply_smb1_outbuf ( req , 1 , 0 ) ;
2008-10-19 17:30:12 +04:00
2007-08-14 22:16:04 +04:00
SSVAL ( req - > outbuf , smb_vwv0 , nwritten ) ;
1996-05-04 11:50:46 +04:00
2001-11-25 05:23:22 +03:00
if ( nwritten < ( ssize_t ) numtowrite ) {
2007-08-14 22:16:04 +04:00
SCVAL ( req - > outbuf , smb_rcls , ERRHRD ) ;
SSVAL ( req - > outbuf , smb_err , ERRdiskfull ) ;
2001-11-25 05:23:22 +03:00
}
2008-10-19 17:30:12 +04:00
2012-06-14 15:10:33 +04:00
DEBUG ( 3 , ( " write %s num=%d wrote=%d \n " , fsp_fnum_dbg ( fsp ) , ( int ) numtowrite , ( int ) nwritten ) ) ;
1998-08-01 02:39:15 +04:00
2017-07-09 15:21:21 +03:00
out :
2001-11-25 05:23:22 +03:00
END_PROFILE ( SMBwrite ) ;
2007-08-14 22:16:04 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
2007-10-31 02:22:24 +03:00
/****************************************************************************
Ensure a buffer is a valid writeX for recvfile purposes .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
( 2 * 14 ) + /* word count (including bcc) */ \
1 /* pad byte */ )
2014-06-11 16:35:55 +04:00
bool is_valid_writeX_buffer ( struct smbXsrv_connection * xconn ,
2010-06-12 13:55:42 +04:00
const uint8_t * inbuf )
2007-10-31 02:22:24 +03:00
{
size_t numtowrite ;
unsigned int doff = 0 ;
2007-11-02 22:21:34 +03:00
size_t len = smb_len_large ( inbuf ) ;
2014-04-11 02:51:32 +04:00
uint16_t fnum ;
struct smbXsrv_open * op = NULL ;
struct files_struct * fsp = NULL ;
2012-03-28 18:14:09 +04:00
NTSTATUS status ;
2007-10-31 02:22:24 +03:00
2014-06-11 16:28:13 +04:00
if ( is_encrypted_packet ( inbuf ) ) {
2007-12-27 04:12:36 +03:00
/* Can't do this on encrypted
* connections . */
return false ;
}
2007-11-08 08:47:00 +03:00
if ( CVAL ( inbuf , smb_com ) ! = SMBwriteX ) {
return false ;
}
if ( CVAL ( inbuf , smb_vwv0 ) ! = 0xFF | |
2007-10-31 02:22:24 +03:00
CVAL ( inbuf , smb_wct ) ! = 14 ) {
2007-11-08 08:47:00 +03:00
DEBUG ( 10 , ( " is_valid_writeX_buffer: chained or "
" invalid word length. \n " ) ) ;
2007-10-31 02:22:24 +03:00
return false ;
}
2007-11-08 08:47:00 +03:00
2014-04-11 02:51:32 +04:00
fnum = SVAL ( inbuf , smb_vwv2 ) ;
2014-06-11 16:35:55 +04:00
status = smb1srv_open_lookup ( xconn ,
2014-04-11 02:51:32 +04:00
fnum ,
0 , /* now */
& op ) ;
2012-03-28 18:14:09 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2014-04-11 02:51:32 +04:00
DEBUG ( 10 , ( " is_valid_writeX_buffer: bad fnum \n " ) ) ;
return false ;
}
fsp = op - > compat ;
if ( fsp = = NULL ) {
DEBUG ( 10 , ( " is_valid_writeX_buffer: bad fsp \n " ) ) ;
return false ;
}
if ( fsp - > conn = = NULL ) {
DEBUG ( 10 , ( " is_valid_writeX_buffer: bad fsp->conn \n " ) ) ;
2007-10-31 02:22:24 +03:00
return false ;
}
2012-03-28 18:14:09 +04:00
2014-04-11 02:51:32 +04:00
if ( IS_IPC ( fsp - > conn ) ) {
2007-11-08 08:47:00 +03:00
DEBUG ( 10 , ( " is_valid_writeX_buffer: IPC$ tid \n " ) ) ;
2007-10-31 02:22:24 +03:00
return false ;
}
2014-04-11 02:51:32 +04:00
if ( IS_PRINT ( fsp - > conn ) ) {
2008-12-31 20:37:39 +03:00
DEBUG ( 10 , ( " is_valid_writeX_buffer: printing tid \n " ) ) ;
return false ;
}
2022-02-11 11:37:35 +03:00
if ( fsp_is_alternate_stream ( fsp ) ) {
2019-05-09 22:53:11 +03:00
DEBUG ( 10 , ( " is_valid_writeX_buffer: stream fsp \n " ) ) ;
return false ;
}
2007-11-02 22:21:34 +03:00
doff = SVAL ( inbuf , smb_vwv11 ) ;
2007-10-31 02:22:24 +03:00
numtowrite = SVAL ( inbuf , smb_vwv10 ) ;
2007-11-02 22:21:34 +03:00
if ( len > doff & & len - doff > 0xFFFF ) {
numtowrite | = ( ( ( size_t ) SVAL ( inbuf , smb_vwv9 ) ) < < 16 ) ;
}
2007-10-31 02:22:24 +03:00
if ( numtowrite = = 0 ) {
2007-11-08 08:47:00 +03:00
DEBUG ( 10 , ( " is_valid_writeX_buffer: zero write \n " ) ) ;
2007-10-31 02:22:24 +03:00
return false ;
}
2007-11-02 22:21:34 +03:00
/* Ensure the sizes match up. */
2007-10-31 02:22:24 +03:00
if ( doff < STANDARD_WRITE_AND_X_HEADER_SIZE ) {
/* no pad byte...old smbclient :-( */
2007-11-08 08:47:00 +03:00
DEBUG ( 10 , ( " is_valid_writeX_buffer: small doff %u (min %u) \n " ,
( unsigned int ) doff ,
( unsigned int ) STANDARD_WRITE_AND_X_HEADER_SIZE ) ) ;
2007-10-31 02:22:24 +03:00
return false ;
}
if ( len - doff ! = numtowrite ) {
DEBUG ( 10 , ( " is_valid_writeX_buffer: doff mismatch "
" len = %u, doff = %u, numtowrite = %u \n " ,
( unsigned int ) len ,
( unsigned int ) doff ,
( unsigned int ) numtowrite ) ) ;
return false ;
}
DEBUG ( 10 , ( " is_valid_writeX_buffer: true "
" len = %u, doff = %u, numtowrite = %u \n " ,
( unsigned int ) len ,
( unsigned int ) doff ,
( unsigned int ) numtowrite ) ) ;
return true ;
}
1996-05-04 11:50:46 +04:00
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a write and X .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2008-01-05 02:37:24 +03:00
void reply_write_and_X ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
2014-06-11 17:12:32 +04:00
struct smbXsrv_connection * xconn = req - > xconn ;
2007-08-07 17:12:46 +04:00
files_struct * fsp ;
2009-03-14 00:15:28 +03:00
struct lock_struct lock ;
2012-04-05 08:53:08 +04:00
off_t startpos ;
2007-08-07 17:12:46 +04:00
size_t numtowrite ;
2007-10-19 04:40:25 +04:00
bool write_through ;
2007-08-07 17:12:46 +04:00
ssize_t nwritten ;
unsigned int smb_doff ;
unsigned int smblen ;
2011-05-05 21:41:59 +04:00
const char * data ;
2007-06-15 23:24:04 +04:00
NTSTATUS status ;
2010-04-06 01:16:21 +04:00
int saved_errno = 0 ;
2007-08-07 17:12:46 +04:00
2002-12-04 02:57:45 +03:00
START_PROFILE ( SMBwriteX ) ;
2007-08-08 22:40:26 +04:00
if ( ( req - > wct ! = 12 ) & & ( req - > wct ! = 14 ) ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
2012-03-05 18:47:52 +04:00
goto out ;
2007-08-07 17:43:02 +04:00
}
2008-11-02 14:20:47 +03:00
numtowrite = SVAL ( req - > vwv + 10 , 0 ) ;
smb_doff = SVAL ( req - > vwv + 11 , 0 ) ;
2007-08-08 22:40:26 +04:00
smblen = smb_len ( req - > inbuf ) ;
2007-11-02 08:24:39 +03:00
if ( req - > unread_bytes > 0xFFFF | |
2007-11-02 20:35:10 +03:00
( smblen > smb_doff & &
smblen - smb_doff > 0xFFFF ) ) {
2008-11-02 14:20:47 +03:00
numtowrite | = ( ( ( size_t ) SVAL ( req - > vwv + 9 , 0 ) ) < < 16 ) ;
2007-08-08 22:40:26 +04:00
}
2007-10-31 02:22:24 +03:00
if ( req - > unread_bytes ) {
2007-11-08 08:47:00 +03:00
/* Can't do a recvfile write on IPC$ */
if ( IS_IPC ( conn ) ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
2012-03-05 18:47:52 +04:00
goto out ;
2007-11-08 08:47:00 +03:00
}
2007-10-31 02:22:24 +03:00
if ( numtowrite ! = req - > unread_bytes ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
2012-03-05 18:47:52 +04:00
goto out ;
2007-10-31 02:22:24 +03:00
}
} else {
2017-09-08 20:13:14 +03:00
/*
* This already protects us against CVE - 2017 - 12163.
*/
2007-11-02 20:35:10 +03:00
if ( smb_doff > smblen | | smb_doff + numtowrite < numtowrite | |
smb_doff + numtowrite > smblen ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
2012-03-05 18:47:52 +04:00
goto out ;
2007-10-31 02:22:24 +03:00
}
2007-08-07 17:12:46 +04:00
}
2002-12-04 02:57:45 +03:00
/* If it's an IPC, pass off the pipe handler. */
if ( IS_IPC ( conn ) ) {
2007-11-02 08:42:21 +03:00
if ( req - > unread_bytes ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
2012-03-05 18:47:52 +04:00
goto out ;
2007-11-02 08:42:21 +03:00
}
2007-08-08 22:40:26 +04:00
reply_pipe_write_and_X ( req ) ;
2012-03-05 18:47:52 +04:00
goto out ;
2007-08-07 17:43:02 +04:00
}
2008-11-02 14:20:47 +03:00
fsp = file_fsp ( req , SVAL ( req - > vwv + 2 , 0 ) ) ;
startpos = IVAL_TO_SMB_OFF_T ( req - > vwv + 3 , 0 ) ;
write_through = BITSETW ( req - > vwv + 7 , 0 ) ;
2007-08-08 22:40:26 +04:00
2008-06-19 18:31:59 +04:00
if ( ! check_fsp ( conn , req , fsp ) ) {
2012-03-05 18:47:52 +04:00
goto out ;
2002-12-04 02:57:45 +03:00
}
2005-07-08 08:51:27 +04:00
if ( ! CHECK_WRITE ( fsp ) ) {
2009-12-19 01:25:39 +03:00
reply_nterror ( req , NT_STATUS_ACCESS_DENIED ) ;
2012-03-05 18:47:52 +04:00
goto out ;
2005-07-08 08:51:27 +04:00
}
2002-12-04 02:57:45 +03:00
2007-08-08 23:05:30 +04:00
data = smb_base ( req - > inbuf ) + smb_doff ;
2002-12-04 02:57:45 +03:00
2007-08-08 23:05:30 +04:00
if ( req - > wct = = 14 ) {
2002-12-04 02:57:45 +03:00
/*
* This is a large offset ( 64 bit ) write .
*/
2012-04-05 08:53:08 +04:00
startpos | = ( ( ( off_t ) IVAL ( req - > vwv + 12 , 0 ) ) < < 32 ) ;
1999-12-13 16:27:58 +03:00
2002-12-04 02:57:45 +03:00
}
/* X/Open SMB protocol says that, unlike SMBwrite
if the length is zero then NO truncation is
done , just a write of zero . To truncate a file ,
use SMBwrite . */
2005-06-09 22:15:23 +04:00
if ( numtowrite = = 0 ) {
2002-12-04 02:57:45 +03:00
nwritten = 0 ;
2005-06-09 22:15:23 +04:00
} else {
2010-04-06 01:16:21 +04:00
if ( req - > unread_bytes = = 0 ) {
status = schedule_aio_write_and_X ( conn ,
req ,
fsp ,
data ,
startpos ,
numtowrite ) ;
if ( NT_STATUS_IS_OK ( status ) ) {
/* write scheduled - we're done. */
goto out ;
}
if ( ! NT_STATUS_EQUAL ( status , NT_STATUS_RETRY ) ) {
/* Real error - report to client. */
reply_nterror ( req , status ) ;
goto out ;
}
/* NT_STATUS_RETRY - fall through to sync write. */
}
2005-06-09 22:15:23 +04:00
2021-11-17 02:00:03 +03:00
init_strict_lock_struct ( fsp ,
( uint64_t ) req - > smbpid ,
( uint64_t ) startpos ,
( uint64_t ) numtowrite ,
WRITE_LOCK ,
lp_posix_cifsu_locktype ( fsp ) ,
& lock ) ;
2010-04-06 01:16:21 +04:00
2017-07-09 15:34:10 +03:00
if ( ! SMB_VFS_STRICT_LOCK_CHECK ( conn , fsp , & lock ) ) {
2010-04-06 01:16:21 +04:00
reply_nterror ( req , NT_STATUS_FILE_LOCK_CONFLICT ) ;
goto out ;
2005-06-09 22:15:23 +04:00
}
2008-10-19 17:30:12 +04:00
2007-10-31 02:22:24 +03:00
nwritten = write_file ( req , fsp , data , startpos , numtowrite ) ;
2010-04-06 01:16:21 +04:00
saved_errno = errno ;
2005-06-09 22:15:23 +04:00
}
2007-10-31 02:22:24 +03:00
2009-07-11 05:23:00 +04:00
if ( nwritten < 0 ) {
2010-04-06 01:16:21 +04:00
reply_nterror ( req , map_nt_error_from_unix ( saved_errno ) ) ;
goto out ;
2009-07-11 05:23:00 +04:00
}
if ( ( nwritten = = 0 ) & & ( numtowrite ! = 0 ) ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_DISK_FULL ) ;
2010-04-06 01:16:21 +04:00
goto out ;
2002-12-04 02:57:45 +03:00
}
2022-04-05 05:53:20 +03:00
reply_smb1_outbuf ( req , 6 , 0 ) ;
2012-02-26 19:49:09 +04:00
SSVAL ( req - > outbuf , smb_vwv0 , 0xff ) ; /* andx chain ends */
SSVAL ( req - > outbuf , smb_vwv1 , 0 ) ; /* no andx offset */
2007-08-08 23:05:30 +04:00
SSVAL ( req - > outbuf , smb_vwv2 , nwritten ) ;
2007-11-02 08:24:39 +03:00
SSVAL ( req - > outbuf , smb_vwv4 , nwritten > > 16 ) ;
2002-12-04 02:57:45 +03:00
2012-06-14 15:10:33 +04:00
DEBUG ( 3 , ( " writeX %s num=%d wrote=%d \n " ,
fsp_fnum_dbg ( fsp ) , ( int ) numtowrite , ( int ) nwritten ) ) ;
2002-12-04 02:57:45 +03:00
2007-06-15 23:24:04 +04:00
status = sync_file ( conn , fsp , write_through ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 5 , ( " reply_write_and_X: sync_file for %s returned %s \n " ,
2009-07-11 01:50:37 +04:00
fsp_str_dbg ( fsp ) , nt_errstr ( status ) ) ) ;
2007-08-07 17:43:02 +04:00
reply_nterror ( req , status ) ;
2010-04-06 01:16:21 +04:00
goto out ;
2007-06-15 23:24:04 +04:00
}
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBwriteX ) ;
2007-08-07 17:43:02 +04:00
return ;
2009-03-14 00:15:28 +03:00
2010-04-06 01:16:21 +04:00
out :
2012-03-05 18:40:49 +04:00
if ( req - > unread_bytes ) {
/* writeX failed. drain socket. */
2014-05-22 01:23:34 +04:00
if ( drain_socket ( xconn - > transport . sock , req - > unread_bytes ) ! =
2012-03-05 18:40:49 +04:00
req - > unread_bytes ) {
smb_panic ( " failed to drain pending bytes " ) ;
}
req - > unread_bytes = 0 ;
}
2009-03-14 00:15:28 +03:00
END_PROFILE ( SMBwriteX ) ;
return ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a lseek .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
2008-01-05 02:37:24 +03:00
void reply_lseek ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
2012-04-05 08:53:08 +04:00
off_t startpos ;
off_t res = - 1 ;
2002-12-04 02:57:45 +03:00
int mode , umode ;
2007-08-14 20:04:31 +04:00
files_struct * fsp ;
2019-09-09 08:57:34 +03:00
NTSTATUS status ;
2007-08-14 20:04:31 +04:00
2002-12-04 02:57:45 +03:00
START_PROFILE ( SMBlseek ) ;
1996-05-04 11:50:46 +04:00
2007-08-14 20:04:31 +04:00
if ( req - > wct < 4 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBlseek ) ;
return ;
}
2008-11-02 14:20:47 +03:00
fsp = file_fsp ( req , SVAL ( req - > vwv + 0 , 0 ) ) ;
2007-08-14 20:04:31 +04:00
2008-06-19 18:31:59 +04:00
if ( ! check_fsp ( conn , req , fsp ) ) {
2007-08-14 20:04:31 +04:00
return ;
}
1996-05-04 11:50:46 +04:00
2008-11-02 14:20:47 +03:00
mode = SVAL ( req - > vwv + 1 , 0 ) & 3 ;
2002-12-04 02:57:45 +03:00
/* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
2012-04-05 08:53:08 +04:00
startpos = ( off_t ) IVALS ( req - > vwv + 2 , 0 ) ;
1996-05-04 11:50:46 +04:00
2002-12-04 02:57:45 +03:00
switch ( mode ) {
case 0 :
umode = SEEK_SET ;
2003-08-15 01:16:06 +04:00
res = startpos ;
2002-12-04 02:57:45 +03:00
break ;
case 1 :
umode = SEEK_CUR ;
2020-09-28 11:32:29 +03:00
res = fh_get_pos ( fsp - > fh ) + startpos ;
2002-12-04 02:57:45 +03:00
break ;
case 2 :
umode = SEEK_END ;
break ;
default :
umode = SEEK_SET ;
2003-08-15 01:16:06 +04:00
res = startpos ;
2002-12-04 02:57:45 +03:00
break ;
}
1998-07-31 01:18:57 +04:00
2003-08-15 01:16:06 +04:00
if ( umode = = SEEK_END ) {
2008-01-07 12:15:08 +03:00
if ( ( res = SMB_VFS_LSEEK ( fsp , startpos , umode ) ) = = - 1 ) {
2003-08-15 01:16:06 +04:00
if ( errno = = EINVAL ) {
2012-04-05 08:53:08 +04:00
off_t current_pos = startpos ;
1999-12-13 16:27:58 +03:00
2019-09-09 08:57:34 +03:00
status = vfs_stat_fsp ( fsp ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
reply_nterror ( req , status ) ;
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBlseek ) ;
2007-08-14 20:04:31 +04:00
return ;
2002-12-04 02:57:45 +03:00
}
1999-12-13 16:27:58 +03:00
2009-11-18 03:06:08 +03:00
current_pos + = fsp - > fsp_name - > st . st_ex_size ;
2003-08-15 01:16:06 +04:00
if ( current_pos < 0 )
2008-01-07 12:15:08 +03:00
res = SMB_VFS_LSEEK ( fsp , 0 , SEEK_SET ) ;
2002-12-04 02:57:45 +03:00
}
}
1999-12-13 16:27:58 +03:00
2002-12-04 02:57:45 +03:00
if ( res = = - 1 ) {
2009-07-11 05:23:00 +04:00
reply_nterror ( req , map_nt_error_from_unix ( errno ) ) ;
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBlseek ) ;
2007-08-14 20:04:31 +04:00
return ;
2002-12-04 02:57:45 +03:00
}
}
1998-10-19 02:06:35 +04:00
2020-09-28 11:32:29 +03:00
fh_set_pos ( fsp - > fh , res ) ;
2007-08-14 20:04:31 +04:00
2022-04-05 05:53:20 +03:00
reply_smb1_outbuf ( req , 2 , 0 ) ;
2007-08-14 20:04:31 +04:00
SIVAL ( req - > outbuf , smb_vwv0 , res ) ;
2008-10-19 17:30:12 +04:00
2012-06-14 15:10:33 +04:00
DEBUG ( 3 , ( " lseek %s ofs=%.0f newpos = %.0f mode=%d \n " ,
fsp_fnum_dbg ( fsp ) , ( double ) startpos , ( double ) res , mode ) ) ;
1998-08-01 02:39:15 +04:00
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBlseek ) ;
2007-08-14 20:04:31 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
2018-09-13 07:21:37 +03:00
static struct files_struct * file_sync_one_fn ( struct files_struct * fsp ,
void * private_data )
{
connection_struct * conn = talloc_get_type_abort (
private_data , connection_struct ) ;
if ( conn ! = fsp - > conn ) {
return NULL ;
}
2020-09-26 22:52:52 +03:00
if ( fsp_get_io_fd ( fsp ) = = - 1 ) {
2018-09-13 07:21:37 +03:00
return NULL ;
}
sync_file ( conn , fsp , True /* write through */ ) ;
2020-04-02 18:37:02 +03:00
if ( fsp - > fsp_flags . modified ) {
2020-03-12 21:23:40 +03:00
trigger_write_time_update_immediate ( fsp ) ;
}
2018-09-13 07:21:37 +03:00
return NULL ;
}
1996-05-04 11:50:46 +04:00
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a flush .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
2008-01-05 02:37:24 +03:00
void reply_flush ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
2015-04-27 02:02:55 +03:00
uint16_t fnum ;
2007-08-05 00:44:33 +04:00
files_struct * fsp ;
2001-08-24 08:56:33 +04:00
START_PROFILE ( SMBflush ) ;
1996-05-04 11:50:46 +04:00
2007-08-05 00:44:33 +04:00
if ( req - > wct < 1 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
return ;
}
2008-11-02 14:20:47 +03:00
fnum = SVAL ( req - > vwv + 0 , 0 ) ;
2008-10-09 17:25:17 +04:00
fsp = file_fsp ( req , fnum ) ;
2007-08-05 00:44:33 +04:00
2008-06-19 18:31:59 +04:00
if ( ( fnum ! = 0xFFFF ) & & ! check_fsp ( conn , req , fsp ) ) {
2007-08-05 00:44:33 +04:00
return ;
}
2008-10-19 17:30:12 +04:00
2001-08-24 08:56:33 +04:00
if ( ! fsp ) {
2018-09-13 07:21:37 +03:00
files_forall ( req - > sconn , file_sync_one_fn , conn ) ;
2001-08-24 08:56:33 +04:00
} else {
2007-06-15 23:24:04 +04:00
NTSTATUS status = sync_file ( conn , fsp , True ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 5 , ( " reply_flush: sync_file for %s returned %s \n " ,
2009-07-11 01:50:37 +04:00
fsp_str_dbg ( fsp ) , nt_errstr ( status ) ) ) ;
2007-08-05 00:44:33 +04:00
reply_nterror ( req , status ) ;
END_PROFILE ( SMBflush ) ;
return ;
2007-06-15 23:24:04 +04:00
}
2020-04-02 18:37:02 +03:00
if ( fsp - > fsp_flags . modified ) {
2020-03-12 21:23:40 +03:00
trigger_write_time_update_immediate ( fsp ) ;
}
2001-08-24 08:56:33 +04:00
}
2008-10-19 17:30:12 +04:00
2022-04-05 05:53:20 +03:00
reply_smb1_outbuf ( req , 0 , 0 ) ;
2007-08-05 00:44:33 +04:00
2001-08-24 08:56:33 +04:00
DEBUG ( 3 , ( " flush \n " ) ) ;
END_PROFILE ( SMBflush ) ;
2007-08-05 00:44:33 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a exit .
2006-06-20 06:38:28 +04:00
conn POINTER CAN BE NULL HERE !
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2020-03-12 21:01:05 +03:00
static struct tevent_req * reply_exit_send ( struct smb_request * smb1req ) ;
static void reply_exit_done ( struct tevent_req * req ) ;
2003-08-19 05:53:45 +04:00
2020-03-12 21:01:05 +03:00
void reply_exit ( struct smb_request * smb1req )
{
struct tevent_req * req ;
2000-10-06 07:21:49 +04:00
2020-03-12 21:01:05 +03:00
/*
* Don ' t setup the profile charge here , take
* it in reply_exit_done ( ) . Not strictly correct
* but better than the other SMB1 async
* code that double - charges at the moment .
*/
req = reply_exit_send ( smb1req ) ;
if ( req = = NULL ) {
/* Not going async, profile here. */
START_PROFILE ( SMBexit ) ;
reply_force_doserror ( smb1req , ERRDOS , ERRnomem ) ;
END_PROFILE ( SMBexit ) ;
return ;
}
1998-08-01 02:39:15 +04:00
2020-03-12 21:01:05 +03:00
/* We're async. This will complete later. */
tevent_req_set_callback ( req , reply_exit_done , smb1req ) ;
2007-08-02 09:50:40 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
2020-03-12 20:59:16 +03:00
struct reply_exit_state {
struct tevent_queue * wait_queue ;
} ;
static void reply_exit_wait_done ( struct tevent_req * subreq ) ;
/****************************************************************************
Async SMB1 exit .
Note , on failure here we deallocate and return NULL to allow the caller to
SMB1 return an error of ERRnomem immediately .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static struct tevent_req * reply_exit_send ( struct smb_request * smb1req )
{
struct tevent_req * req ;
struct reply_exit_state * state ;
struct tevent_req * subreq ;
files_struct * fsp ;
struct smbd_server_connection * sconn = smb1req - > sconn ;
req = tevent_req_create ( smb1req , & state ,
struct reply_exit_state ) ;
if ( req = = NULL ) {
return NULL ;
}
state - > wait_queue = tevent_queue_create ( state ,
" reply_exit_wait_queue " ) ;
if ( tevent_req_nomem ( state - > wait_queue , req ) ) {
TALLOC_FREE ( req ) ;
return NULL ;
}
for ( fsp = sconn - > files ; fsp ; fsp = fsp - > next ) {
if ( fsp - > file_pid ! = smb1req - > smbpid ) {
continue ;
}
if ( fsp - > vuid ! = smb1req - > vuid ) {
continue ;
}
/*
* Flag the file as close in progress .
* This will prevent any more IO being
* done on it .
*/
2020-04-03 09:06:27 +03:00
fsp - > fsp_flags . closing = true ;
2020-03-12 20:59:16 +03:00
if ( fsp - > num_aio_requests > 0 ) {
/*
* Now wait until all aio requests on this fsp are
* finished .
*
* We don ' t set a callback , as we just want to block the
* wait queue and the talloc_free ( ) of fsp - > aio_request
* will remove the item from the wait queue .
*/
subreq = tevent_queue_wait_send ( fsp - > aio_requests ,
sconn - > ev_ctx ,
state - > wait_queue ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
TALLOC_FREE ( req ) ;
return NULL ;
}
}
}
/*
* Now we add our own waiter to the end of the queue ,
* this way we get notified when all pending requests are finished
* and reply to the outstanding SMB1 request .
*/
subreq = tevent_queue_wait_send ( state ,
sconn - > ev_ctx ,
state - > wait_queue ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
TALLOC_FREE ( req ) ;
return NULL ;
}
/*
* We ' re really going async - move the SMB1 request from
* a talloc stackframe above us to the conn talloc - context .
* We need this to stick around until the wait_done
* callback is invoked .
*/
smb1req = talloc_move ( sconn , & smb1req ) ;
tevent_req_set_callback ( subreq , reply_exit_wait_done , req ) ;
return req ;
}
static void reply_exit_wait_done ( struct tevent_req * subreq )
{
struct tevent_req * req = tevent_req_callback_data (
subreq , struct tevent_req ) ;
tevent_queue_wait_recv ( subreq ) ;
TALLOC_FREE ( subreq ) ;
tevent_req_done ( req ) ;
}
static NTSTATUS reply_exit_recv ( struct tevent_req * req )
{
return tevent_req_simple_recv_ntstatus ( req ) ;
}
static void reply_exit_done ( struct tevent_req * req )
{
struct smb_request * smb1req = tevent_req_callback_data (
req , struct smb_request ) ;
struct smbd_server_connection * sconn = smb1req - > sconn ;
struct smbXsrv_connection * xconn = smb1req - > xconn ;
NTTIME now = timeval_to_nttime ( & smb1req - > request_time ) ;
struct smbXsrv_session * session = NULL ;
files_struct * fsp , * next ;
NTSTATUS status ;
/*
* Take the profile charge here . Not strictly
* correct but better than the other SMB1 async
* code that double - charges at the moment .
*/
START_PROFILE ( SMBexit ) ;
status = reply_exit_recv ( req ) ;
TALLOC_FREE ( req ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
TALLOC_FREE ( smb1req ) ;
END_PROFILE ( SMBexit ) ;
exit_server ( __location__ " : reply_exit_recv failed " ) ;
return ;
}
/*
* Ensure the session is still valid .
*/
status = smb1srv_session_lookup ( xconn ,
smb1req - > vuid ,
now ,
& session ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
reply_force_doserror ( smb1req , ERRSRV , ERRinvnid ) ;
smb_request_done ( smb1req ) ;
END_PROFILE ( SMBexit ) ;
2023-08-12 01:19:01 +03:00
return ;
2020-03-12 20:59:16 +03:00
}
/*
* Ensure the vuid is still valid - no one
* called reply_ulogoffX ( ) in the meantime .
* reply_exit ( ) doesn ' t have AS_USER set , so
* use set_current_user_info ( ) directly .
* This is the same logic as in switch_message ( ) .
*/
if ( session - > global - > auth_session_info ! = NULL ) {
set_current_user_info (
session - > global - > auth_session_info - > unix_info - > sanitized_username ,
session - > global - > auth_session_info - > unix_info - > unix_name ,
session - > global - > auth_session_info - > info - > domain_name ) ;
}
/* No more aio - do the actual closes. */
for ( fsp = sconn - > files ; fsp ; fsp = next ) {
bool ok ;
next = fsp - > next ;
if ( fsp - > file_pid ! = smb1req - > smbpid ) {
continue ;
}
if ( fsp - > vuid ! = smb1req - > vuid ) {
continue ;
}
2020-04-03 09:06:27 +03:00
if ( ! fsp - > fsp_flags . closing ) {
2020-03-12 20:59:16 +03:00
continue ;
}
/*
* reply_exit ( ) has the DO_CHDIR flag set .
*/
ok = chdir_current_service ( fsp - > conn ) ;
if ( ! ok ) {
reply_force_doserror ( smb1req , ERRSRV , ERRinvnid ) ;
smb_request_done ( smb1req ) ;
END_PROFILE ( SMBexit ) ;
2023-08-12 01:19:01 +03:00
return ;
2020-03-12 20:59:16 +03:00
}
2022-02-01 19:47:29 +03:00
close_file_free ( NULL , & fsp , SHUTDOWN_CLOSE ) ;
2020-03-12 20:59:16 +03:00
}
2022-04-05 05:53:20 +03:00
reply_smb1_outbuf ( smb1req , 0 , 0 ) ;
2020-03-12 20:59:16 +03:00
/*
* The following call is needed to push the
* reply data back out the socket after async
* return . Plus it frees smb1req .
*/
smb_request_done ( smb1req ) ;
DBG_INFO ( " reply_exit complete \n " ) ;
END_PROFILE ( SMBexit ) ;
return ;
}
2020-03-19 01:21:43 +03:00
static struct tevent_req * reply_close_send ( struct smb_request * smb1req ,
files_struct * fsp ) ;
static void reply_close_done ( struct tevent_req * req ) ;
2012-07-18 00:24:51 +04:00
2020-03-19 00:06:38 +03:00
void reply_close ( struct smb_request * smb1req )
1996-05-04 11:50:46 +04:00
{
2020-03-19 00:06:38 +03:00
connection_struct * conn = smb1req - > conn ;
2007-02-07 00:05:34 +03:00
NTSTATUS status = NT_STATUS_OK ;
1998-08-14 21:38:29 +04:00
files_struct * fsp = NULL ;
2000-10-06 07:21:49 +04:00
START_PROFILE ( SMBclose ) ;
1996-05-04 11:50:46 +04:00
2020-03-19 00:06:38 +03:00
if ( smb1req - > wct < 3 ) {
reply_nterror ( smb1req , NT_STATUS_INVALID_PARAMETER ) ;
2007-07-23 13:53:06 +04:00
END_PROFILE ( SMBclose ) ;
return ;
}
1996-05-04 11:50:46 +04:00
2020-03-19 00:06:38 +03:00
fsp = file_fsp ( smb1req , SVAL ( smb1req - > vwv + 0 , 0 ) ) ;
1997-10-30 04:05:13 +03:00
1998-08-14 21:38:29 +04:00
/*
2008-10-08 14:56:04 +04:00
* We can only use check_fsp if we know it ' s not a directory .
1998-08-14 21:38:29 +04:00
*/
1998-07-18 02:21:24 +04:00
2020-03-19 00:06:38 +03:00
if ( ! check_fsp_open ( conn , smb1req , fsp ) ) {
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBclose ) ;
2007-07-23 13:53:06 +04:00
return ;
1998-08-14 21:38:29 +04:00
}
1996-05-04 11:50:46 +04:00
2020-03-19 00:29:30 +03:00
DBG_NOTICE ( " Close %s fd=%d %s (numopen=%d) \n " ,
2020-04-02 19:21:11 +03:00
fsp - > fsp_flags . is_directory ?
" directory " : " file " ,
2020-10-03 18:41:17 +03:00
fsp_get_pathref_fd ( fsp ) , fsp_fnum_dbg ( fsp ) ,
2020-03-19 00:29:30 +03:00
conn - > num_files_open ) ;
1996-05-04 11:50:46 +04:00
2020-04-02 19:21:11 +03:00
if ( ! fsp - > fsp_flags . is_directory ) {
2012-07-17 23:52:13 +04:00
time_t t ;
2008-10-19 17:30:12 +04:00
2005-03-10 04:30:14 +03:00
/*
* Take care of any time sent in the close .
*/
2020-03-19 00:06:38 +03:00
t = srv_make_unix_date3 ( smb1req - > vwv + 1 ) ;
2019-12-02 18:30:50 +03:00
set_close_write_time ( fsp , time_t_to_full_timespec ( t ) ) ;
2012-07-17 23:52:13 +04:00
}
2005-03-10 04:30:14 +03:00
2012-07-18 00:24:51 +04:00
if ( fsp - > num_aio_requests ! = 0 ) {
2020-03-19 01:21:43 +03:00
struct tevent_req * req ;
2012-07-18 00:24:51 +04:00
2020-03-19 01:21:43 +03:00
req = reply_close_send ( smb1req , fsp ) ;
if ( req = = NULL ) {
2012-07-18 00:24:51 +04:00
status = NT_STATUS_NO_MEMORY ;
goto done ;
}
2020-03-19 01:21:43 +03:00
/* We're async. This will complete later. */
tevent_req_set_callback ( req , reply_close_done , smb1req ) ;
2012-07-18 00:24:51 +04:00
END_PROFILE ( SMBclose ) ;
return ;
}
2012-07-17 23:52:13 +04:00
/*
2022-02-01 19:47:29 +03:00
* close_file_free ( ) returns the unix errno if an error was detected on
2012-07-17 23:52:13 +04:00
* close - normally this is due to a disk full error . If not then it
* was probably an I / O error .
*/
2008-10-19 17:30:12 +04:00
2022-02-01 19:47:29 +03:00
status = close_file_free ( smb1req , & fsp , NORMAL_CLOSE ) ;
2012-07-18 00:24:51 +04:00
done :
2007-07-23 13:53:06 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2020-03-19 00:06:38 +03:00
reply_nterror ( smb1req , status ) ;
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBclose ) ;
2007-07-23 13:53:06 +04:00
return ;
2000-10-06 07:21:49 +04:00
}
1996-05-04 11:50:46 +04:00
2022-04-05 05:53:20 +03:00
reply_smb1_outbuf ( smb1req , 0 , 0 ) ;
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBclose ) ;
2007-07-23 13:53:06 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
2020-03-19 01:09:51 +03:00
struct reply_close_state {
files_struct * fsp ;
struct tevent_queue * wait_queue ;
} ;
static void reply_close_wait_done ( struct tevent_req * subreq ) ;
/****************************************************************************
Async SMB1 close .
Note , on failure here we deallocate and return NULL to allow the caller to
SMB1 return an error of ERRnomem immediately .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static struct tevent_req * reply_close_send ( struct smb_request * smb1req ,
files_struct * fsp )
{
struct tevent_req * req ;
struct reply_close_state * state ;
struct tevent_req * subreq ;
struct smbd_server_connection * sconn = smb1req - > sconn ;
req = tevent_req_create ( smb1req , & state ,
struct reply_close_state ) ;
if ( req = = NULL ) {
return NULL ;
}
state - > wait_queue = tevent_queue_create ( state ,
" reply_close_wait_queue " ) ;
if ( tevent_req_nomem ( state - > wait_queue , req ) ) {
TALLOC_FREE ( req ) ;
return NULL ;
}
/*
* Flag the file as close in progress .
* This will prevent any more IO being
* done on it .
*/
2020-04-03 09:06:27 +03:00
fsp - > fsp_flags . closing = true ;
2020-03-19 01:09:51 +03:00
/*
* Now wait until all aio requests on this fsp are
* finished .
*
* We don ' t set a callback , as we just want to block the
* wait queue and the talloc_free ( ) of fsp - > aio_request
* will remove the item from the wait queue .
*/
subreq = tevent_queue_wait_send ( fsp - > aio_requests ,
sconn - > ev_ctx ,
state - > wait_queue ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
TALLOC_FREE ( req ) ;
return NULL ;
}
/*
* Now we add our own waiter to the end of the queue ,
* this way we get notified when all pending requests are finished
* and reply to the outstanding SMB1 request .
*/
subreq = tevent_queue_wait_send ( state ,
sconn - > ev_ctx ,
state - > wait_queue ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
TALLOC_FREE ( req ) ;
return NULL ;
}
/*
* We ' re really going async - move the SMB1 request from
* a talloc stackframe above us to the conn talloc - context .
* We need this to stick around until the wait_done
* callback is invoked .
*/
smb1req = talloc_move ( sconn , & smb1req ) ;
tevent_req_set_callback ( subreq , reply_close_wait_done , req ) ;
return req ;
}
static void reply_close_wait_done ( struct tevent_req * subreq )
{
struct tevent_req * req = tevent_req_callback_data (
subreq , struct tevent_req ) ;
tevent_queue_wait_recv ( subreq ) ;
TALLOC_FREE ( subreq ) ;
tevent_req_done ( req ) ;
}
static NTSTATUS reply_close_recv ( struct tevent_req * req )
{
return tevent_req_simple_recv_ntstatus ( req ) ;
}
static void reply_close_done ( struct tevent_req * req )
{
struct smb_request * smb1req = tevent_req_callback_data (
req , struct smb_request ) ;
struct reply_close_state * state = tevent_req_data ( req ,
struct reply_close_state ) ;
NTSTATUS status ;
status = reply_close_recv ( req ) ;
TALLOC_FREE ( req ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
TALLOC_FREE ( smb1req ) ;
exit_server ( __location__ " : reply_close_recv failed " ) ;
return ;
}
2022-02-01 19:47:29 +03:00
status = close_file_free ( smb1req , & state - > fsp , NORMAL_CLOSE ) ;
2020-03-19 01:09:51 +03:00
if ( NT_STATUS_IS_OK ( status ) ) {
2022-04-05 05:53:20 +03:00
reply_smb1_outbuf ( smb1req , 0 , 0 ) ;
2020-03-19 01:09:51 +03:00
} else {
reply_nterror ( smb1req , status ) ;
}
/*
* The following call is needed to push the
* reply data back out the socket after async
* return . Plus it frees smb1req .
*/
smb_request_done ( smb1req ) ;
}
1996-05-04 11:50:46 +04:00
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a writeclose ( Core + protocol ) .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
2008-01-05 02:37:24 +03:00
void reply_writeclose ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
1998-09-11 05:24:30 +04:00
size_t numtowrite ;
2017-09-08 20:13:14 +03:00
size_t remaining ;
1998-09-11 05:24:30 +04:00
ssize_t nwritten = - 1 ;
2007-02-07 00:05:34 +03:00
NTSTATUS close_status = NT_STATUS_OK ;
2012-04-05 08:53:08 +04:00
off_t startpos ;
2008-11-01 19:35:48 +03:00
const char * data ;
2007-03-06 02:40:03 +03:00
struct timespec mtime ;
2007-08-14 23:29:02 +04:00
files_struct * fsp ;
2009-03-14 00:15:28 +03:00
struct lock_struct lock ;
2007-08-14 23:29:02 +04:00
2000-10-06 07:21:49 +04:00
START_PROFILE ( SMBwriteclose ) ;
1998-08-14 21:38:29 +04:00
2007-08-14 23:29:02 +04:00
if ( req - > wct < 6 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBwriteclose ) ;
return ;
}
2008-11-02 14:20:47 +03:00
fsp = file_fsp ( req , SVAL ( req - > vwv + 0 , 0 ) ) ;
2007-08-14 23:29:02 +04:00
2008-06-19 18:31:59 +04:00
if ( ! check_fsp ( conn , req , fsp ) ) {
2007-08-14 23:29:02 +04:00
END_PROFILE ( SMBwriteclose ) ;
return ;
}
2005-07-08 08:51:27 +04:00
if ( ! CHECK_WRITE ( fsp ) ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_ACCESS_DENIED ) ;
2007-08-14 23:29:02 +04:00
END_PROFILE ( SMBwriteclose ) ;
return ;
2005-07-08 08:51:27 +04:00
}
1998-08-14 21:38:29 +04:00
2008-11-02 14:20:47 +03:00
numtowrite = SVAL ( req - > vwv + 1 , 0 ) ;
startpos = IVAL_TO_SMB_OFF_T ( req - > vwv + 2 , 0 ) ;
2019-12-02 18:30:50 +03:00
mtime = time_t_to_full_timespec ( srv_make_unix_date3 ( req - > vwv + 4 ) ) ;
2008-11-01 19:35:48 +03:00
data = ( const char * ) req - > buf + 1 ;
2008-10-19 17:30:12 +04:00
2017-09-08 20:13:14 +03:00
/*
* Ensure client isn ' t asking us to write more than
* they sent . CVE - 2017 - 12163.
*/
remaining = smbreq_bufrem ( req , data ) ;
if ( numtowrite > remaining ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBwriteclose ) ;
return ;
}
2014-02-28 00:07:11 +04:00
if ( fsp - > print_file = = NULL ) {
2021-11-17 02:00:03 +03:00
init_strict_lock_struct ( fsp ,
( uint64_t ) req - > smbpid ,
( uint64_t ) startpos ,
( uint64_t ) numtowrite ,
WRITE_LOCK ,
lp_posix_cifsu_locktype ( fsp ) ,
& lock ) ;
2009-03-14 00:15:28 +03:00
2017-07-09 15:34:10 +03:00
if ( ! SMB_VFS_STRICT_LOCK_CHECK ( conn , fsp , & lock ) ) {
2009-12-19 01:25:39 +03:00
reply_nterror ( req , NT_STATUS_FILE_LOCK_CONFLICT ) ;
2009-03-14 00:15:28 +03:00
END_PROFILE ( SMBwriteclose ) ;
return ;
}
2000-10-06 07:21:49 +04:00
}
2008-10-19 17:30:12 +04:00
2007-10-31 02:22:24 +03:00
nwritten = write_file ( req , fsp , data , startpos , numtowrite ) ;
1996-05-04 11:50:46 +04:00
2009-11-06 09:58:12 +03:00
set_close_write_time ( fsp , mtime ) ;
2008-03-12 17:39:38 +03:00
2003-10-10 01:04:48 +04:00
/*
* More insanity . W2K only closes the file if writelen > 0.
* JRA .
*/
2014-02-28 00:07:11 +04:00
DEBUG ( 3 , ( " writeclose %s num=%d wrote=%d (numopen=%d) \n " ,
fsp_fnum_dbg ( fsp ) , ( int ) numtowrite , ( int ) nwritten ,
( numtowrite ) ? conn - > num_files_open - 1 : conn - > num_files_open ) ) ;
2003-10-10 01:04:48 +04:00
if ( numtowrite ) {
2009-07-11 01:50:37 +04:00
DEBUG ( 3 , ( " reply_writeclose: zero length write doesn't close "
" file %s \n " , fsp_str_dbg ( fsp ) ) ) ;
2022-02-01 19:47:29 +03:00
close_status = close_file_free ( req , & fsp , NORMAL_CLOSE ) ;
2003-10-10 01:04:48 +04:00
}
1996-06-04 10:42:03 +04:00
2003-01-09 02:49:21 +03:00
if ( ( ( nwritten = = 0 ) & & ( numtowrite ! = 0 ) ) | | ( nwritten < 0 ) ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_DISK_FULL ) ;
2014-02-28 00:07:11 +04:00
goto out ;
2000-10-06 07:21:49 +04:00
}
2008-10-19 17:30:12 +04:00
2007-02-07 00:05:34 +03:00
if ( ! NT_STATUS_IS_OK ( close_status ) ) {
2007-08-14 23:29:02 +04:00
reply_nterror ( req , close_status ) ;
2014-02-28 00:07:11 +04:00
goto out ;
1999-12-13 16:27:58 +03:00
}
2007-08-14 23:29:02 +04:00
2022-04-05 05:53:20 +03:00
reply_smb1_outbuf ( req , 1 , 0 ) ;
2008-10-19 17:30:12 +04:00
2007-08-14 23:29:02 +04:00
SSVAL ( req - > outbuf , smb_vwv0 , nwritten ) ;
2009-03-14 00:15:28 +03:00
2014-02-28 00:07:11 +04:00
out :
2009-03-14 00:15:28 +03:00
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBwriteclose ) ;
2007-08-14 23:29:02 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
2005-04-27 22:32:37 +04:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_LOCKING
1996-05-04 11:50:46 +04:00
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a lock .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2019-06-13 13:56:13 +03:00
static void reply_lock_done ( struct tevent_req * subreq ) ;
2008-01-05 02:37:24 +03:00
void reply_lock ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2019-06-13 13:56:13 +03:00
struct tevent_req * subreq = NULL ;
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
2007-08-14 22:52:58 +04:00
files_struct * fsp ;
2019-06-13 13:56:13 +03:00
struct smbd_lock_element * lck = NULL ;
2003-10-09 05:46:01 +04:00
2000-10-06 07:21:49 +04:00
START_PROFILE ( SMBlock ) ;
1996-05-04 11:50:46 +04:00
2007-08-14 22:52:58 +04:00
if ( req - > wct < 5 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBlock ) ;
return ;
}
2008-11-02 14:20:47 +03:00
fsp = file_fsp ( req , SVAL ( req - > vwv + 0 , 0 ) ) ;
2007-08-14 22:52:58 +04:00
2008-06-19 18:31:59 +04:00
if ( ! check_fsp ( conn , req , fsp ) ) {
2007-08-14 22:52:58 +04:00
END_PROFILE ( SMBlock ) ;
return ;
}
1996-05-04 11:50:46 +04:00
2019-06-13 13:56:13 +03:00
lck = talloc ( req , struct smbd_lock_element ) ;
if ( lck = = NULL ) {
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
END_PROFILE ( SMBlock ) ;
return ;
}
1996-05-04 11:50:46 +04:00
2019-06-13 13:56:13 +03:00
* lck = ( struct smbd_lock_element ) {
2019-08-08 20:26:28 +03:00
. req_guid = smbd_request_guid ( req , 0 ) ,
2019-06-13 13:56:13 +03:00
. smblctx = req - > smbpid ,
. brltype = WRITE_LOCK ,
2021-11-17 01:26:44 +03:00
. lock_flav = WINDOWS_LOCK ,
2019-06-13 13:56:13 +03:00
. count = IVAL ( req - > vwv + 1 , 0 ) ,
. offset = IVAL ( req - > vwv + 3 , 0 ) ,
} ;
2006-07-18 05:05:51 +04:00
2019-06-13 13:56:13 +03:00
DBG_NOTICE ( " lock fd=%d %s offset=% " PRIu64 " count=% " PRIu64 " \n " ,
2020-09-26 22:52:52 +03:00
fsp_get_io_fd ( fsp ) ,
2019-06-13 13:56:13 +03:00
fsp_fnum_dbg ( fsp ) ,
lck - > offset ,
lck - > count ) ;
2006-07-18 01:09:02 +04:00
2019-06-13 13:56:13 +03:00
subreq = smbd_smb1_do_locks_send (
fsp ,
req - > sconn - > ev_ctx ,
& req ,
fsp ,
0 ,
false , /* large_offset */
1 ,
lck ) ;
if ( subreq = = NULL ) {
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
2001-08-27 12:19:43 +04:00
END_PROFILE ( SMBlock ) ;
2007-08-14 22:52:58 +04:00
return ;
2000-10-06 07:21:49 +04:00
}
2019-06-13 13:56:13 +03:00
tevent_req_set_callback ( subreq , reply_lock_done , NULL ) ;
END_PROFILE ( SMBlock ) ;
}
1998-08-01 02:39:15 +04:00
2019-06-13 13:56:13 +03:00
static void reply_lock_done ( struct tevent_req * subreq )
{
struct smb_request * req = NULL ;
NTSTATUS status ;
bool ok ;
START_PROFILE ( SMBlock ) ;
ok = smbd_smb1_do_locks_extract_smbreq ( subreq , talloc_tos ( ) , & req ) ;
SMB_ASSERT ( ok ) ;
status = smbd_smb1_do_locks_recv ( subreq ) ;
TALLOC_FREE ( subreq ) ;
if ( NT_STATUS_IS_OK ( status ) ) {
2022-04-05 05:53:20 +03:00
reply_smb1_outbuf ( req , 0 , 0 ) ;
2019-06-13 13:56:13 +03:00
} else {
reply_nterror ( req , status ) ;
}
2007-08-14 22:52:58 +04:00
2022-03-31 22:09:13 +03:00
ok = smb1_srv_send ( req - > xconn ,
2023-06-05 16:45:35 +03:00
( char * ) req - > outbuf ,
true ,
req - > seqnum + 1 ,
IS_CONN_ENCRYPTED ( req - > conn ) ) ;
2019-06-13 13:56:13 +03:00
if ( ! ok ) {
2022-03-31 22:09:13 +03:00
exit_server_cleanly ( " reply_lock_done: smb1_srv_send failed. " ) ;
2019-06-13 13:56:13 +03:00
}
TALLOC_FREE ( req ) ;
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBlock ) ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a unlock .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2008-01-05 02:37:24 +03:00
void reply_unlock ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
2001-08-27 12:19:43 +04:00
NTSTATUS status ;
2007-08-14 23:09:37 +04:00
files_struct * fsp ;
2019-06-14 15:34:08 +03:00
struct smbd_lock_element lck ;
2007-08-14 23:09:37 +04:00
2001-08-27 12:19:43 +04:00
START_PROFILE ( SMBunlock ) ;
1996-05-04 11:50:46 +04:00
2007-08-14 23:09:37 +04:00
if ( req - > wct < 5 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBunlock ) ;
return ;
}
2008-11-02 14:20:47 +03:00
fsp = file_fsp ( req , SVAL ( req - > vwv + 0 , 0 ) ) ;
2007-08-14 23:09:37 +04:00
2008-06-19 18:31:59 +04:00
if ( ! check_fsp ( conn , req , fsp ) ) {
2007-08-14 23:09:37 +04:00
END_PROFILE ( SMBunlock ) ;
return ;
}
2008-10-19 17:30:12 +04:00
2019-06-14 15:34:08 +03:00
lck = ( struct smbd_lock_element ) {
2019-08-08 20:26:28 +03:00
. req_guid = smbd_request_guid ( req , 0 ) ,
2019-06-14 15:34:08 +03:00
. smblctx = req - > smbpid ,
. brltype = UNLOCK_LOCK ,
2021-11-17 01:26:44 +03:00
. lock_flav = WINDOWS_LOCK ,
2019-06-14 15:34:08 +03:00
. offset = IVAL ( req - > vwv + 3 , 0 ) ,
. count = IVAL ( req - > vwv + 1 , 0 ) ,
} ;
2008-10-19 17:30:12 +04:00
2021-11-17 04:04:02 +03:00
status = smbd_do_unlocking ( req , fsp , 1 , & lck ) ;
2006-04-10 19:33:04 +04:00
2019-06-14 15:33:03 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-14 23:09:37 +04:00
reply_nterror ( req , status ) ;
2001-08-27 12:19:43 +04:00
END_PROFILE ( SMBunlock ) ;
2007-08-14 23:09:37 +04:00
return ;
2001-08-27 12:19:43 +04:00
}
1996-05-04 11:50:46 +04:00
2019-06-14 15:00:35 +03:00
DBG_NOTICE ( " unlock fd=%d %s offset=% " PRIu64 " count=% " PRIu64 " \n " ,
2020-09-26 22:52:52 +03:00
fsp_get_io_fd ( fsp ) ,
2019-06-14 15:00:35 +03:00
fsp_fnum_dbg ( fsp ) ,
2019-06-14 15:34:08 +03:00
lck . offset ,
lck . count ) ;
2007-08-14 23:09:37 +04:00
2022-04-05 05:53:20 +03:00
reply_smb1_outbuf ( req , 0 , 0 ) ;
2007-08-14 23:09:37 +04:00
2001-08-27 12:19:43 +04:00
END_PROFILE ( SMBunlock ) ;
2007-08-14 23:09:37 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
2005-04-27 22:32:37 +04:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_ALL
1996-05-04 11:50:46 +04:00
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a tdis .
2006-06-20 06:38:28 +04:00
conn POINTER CAN BE NULL HERE !
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2020-03-12 20:03:27 +03:00
static struct tevent_req * reply_tdis_send ( struct smb_request * smb1req ) ;
static void reply_tdis_done ( struct tevent_req * req ) ;
2020-03-12 19:55:30 +03:00
void reply_tdis ( struct smb_request * smb1req )
1996-05-04 11:50:46 +04:00
{
2020-03-12 19:55:30 +03:00
connection_struct * conn = smb1req - > conn ;
2020-03-12 20:03:27 +03:00
struct tevent_req * req ;
2012-03-28 18:14:09 +04:00
2020-03-12 20:03:27 +03:00
/*
* Don ' t setup the profile charge here , take
* it in reply_tdis_done ( ) . Not strictly correct
* but better than the other SMB1 async
* code that double - charges at the moment .
*/
1996-10-26 00:30:22 +04:00
2020-03-12 19:59:47 +03:00
if ( conn = = NULL ) {
2020-03-12 20:03:27 +03:00
/* Not going async, profile here. */
START_PROFILE ( SMBtdis ) ;
2020-03-12 19:59:47 +03:00
DBG_INFO ( " Invalid connection in tdis \n " ) ;
2020-03-12 19:55:30 +03:00
reply_force_doserror ( smb1req , ERRSRV , ERRinvnid ) ;
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBtdis ) ;
2007-07-30 14:20:52 +04:00
return ;
1998-08-14 21:38:29 +04:00
}
1996-07-03 05:58:27 +04:00
2020-03-12 20:03:27 +03:00
req = reply_tdis_send ( smb1req ) ;
if ( req = = NULL ) {
/* Not going async, profile here. */
START_PROFILE ( SMBtdis ) ;
reply_force_doserror ( smb1req , ERRDOS , ERRnomem ) ;
2012-03-28 18:14:09 +04:00
END_PROFILE ( SMBtdis ) ;
return ;
}
2020-03-12 20:03:27 +03:00
/* We're async. This will complete later. */
tevent_req_set_callback ( req , reply_tdis_done , smb1req ) ;
2007-07-30 14:20:52 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
2020-03-12 19:51:53 +03:00
struct reply_tdis_state {
struct tevent_queue * wait_queue ;
} ;
static void reply_tdis_wait_done ( struct tevent_req * subreq ) ;
/****************************************************************************
Async SMB1 tdis .
Note , on failure here we deallocate and return NULL to allow the caller to
SMB1 return an error of ERRnomem immediately .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static struct tevent_req * reply_tdis_send ( struct smb_request * smb1req )
{
struct tevent_req * req ;
struct reply_tdis_state * state ;
struct tevent_req * subreq ;
connection_struct * conn = smb1req - > conn ;
files_struct * fsp ;
req = tevent_req_create ( smb1req , & state ,
struct reply_tdis_state ) ;
if ( req = = NULL ) {
return NULL ;
}
state - > wait_queue = tevent_queue_create ( state , " reply_tdis_wait_queue " ) ;
if ( tevent_req_nomem ( state - > wait_queue , req ) ) {
TALLOC_FREE ( req ) ;
return NULL ;
}
/*
* Make sure that no new request will be able to use this tcon .
* This ensures that once all outstanding fsp - > aio_requests
* on this tcon are done , we are safe to close it .
*/
conn - > tcon - > status = NT_STATUS_NETWORK_NAME_DELETED ;
for ( fsp = conn - > sconn - > files ; fsp ; fsp = fsp - > next ) {
if ( fsp - > conn ! = conn ) {
continue ;
}
/*
* Flag the file as close in progress .
* This will prevent any more IO being
* done on it . Not strictly needed , but
* doesn ' t hurt to flag it as closing .
*/
2020-04-03 09:06:27 +03:00
fsp - > fsp_flags . closing = true ;
2020-03-12 19:51:53 +03:00
if ( fsp - > num_aio_requests > 0 ) {
/*
* Now wait until all aio requests on this fsp are
* finished .
*
* We don ' t set a callback , as we just want to block the
* wait queue and the talloc_free ( ) of fsp - > aio_request
* will remove the item from the wait queue .
*/
subreq = tevent_queue_wait_send ( fsp - > aio_requests ,
conn - > sconn - > ev_ctx ,
state - > wait_queue ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
TALLOC_FREE ( req ) ;
return NULL ;
}
}
}
/*
* Now we add our own waiter to the end of the queue ,
* this way we get notified when all pending requests are finished
* and reply to the outstanding SMB1 request .
*/
subreq = tevent_queue_wait_send ( state ,
conn - > sconn - > ev_ctx ,
state - > wait_queue ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
TALLOC_FREE ( req ) ;
return NULL ;
}
/*
* We ' re really going async - move the SMB1 request from
* a talloc stackframe above us to the sconn talloc - context .
* We need this to stick around until the wait_done
* callback is invoked .
*/
smb1req = talloc_move ( smb1req - > sconn , & smb1req ) ;
tevent_req_set_callback ( subreq , reply_tdis_wait_done , req ) ;
return req ;
}
static void reply_tdis_wait_done ( struct tevent_req * subreq )
{
struct tevent_req * req = tevent_req_callback_data (
subreq , struct tevent_req ) ;
tevent_queue_wait_recv ( subreq ) ;
TALLOC_FREE ( subreq ) ;
tevent_req_done ( req ) ;
}
static NTSTATUS reply_tdis_recv ( struct tevent_req * req )
{
return tevent_req_simple_recv_ntstatus ( req ) ;
}
static void reply_tdis_done ( struct tevent_req * req )
{
struct smb_request * smb1req = tevent_req_callback_data (
req , struct smb_request ) ;
NTSTATUS status ;
struct smbXsrv_tcon * tcon = smb1req - > conn - > tcon ;
bool ok ;
/*
* Take the profile charge here . Not strictly
* correct but better than the other SMB1 async
* code that double - charges at the moment .
*/
START_PROFILE ( SMBtdis ) ;
status = reply_tdis_recv ( req ) ;
TALLOC_FREE ( req ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
TALLOC_FREE ( smb1req ) ;
END_PROFILE ( SMBtdis ) ;
exit_server ( __location__ " : reply_tdis_recv failed " ) ;
return ;
}
/*
* As we ' ve been awoken , we may have changed
* directory in the meantime .
* reply_tdis ( ) has the DO_CHDIR flag set .
*/
ok = chdir_current_service ( smb1req - > conn ) ;
if ( ! ok ) {
reply_force_doserror ( smb1req , ERRSRV , ERRinvnid ) ;
smb_request_done ( smb1req ) ;
END_PROFILE ( SMBtdis ) ;
}
status = smbXsrv_tcon_disconnect ( tcon ,
smb1req - > vuid ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
TALLOC_FREE ( smb1req ) ;
END_PROFILE ( SMBtdis ) ;
exit_server ( __location__ " : smbXsrv_tcon_disconnect failed " ) ;
return ;
}
/* smbXsrv_tcon_disconnect frees smb1req->conn. */
smb1req - > conn = NULL ;
TALLOC_FREE ( tcon ) ;
2022-04-05 05:53:20 +03:00
reply_smb1_outbuf ( smb1req , 0 , 0 ) ;
2020-03-12 19:51:53 +03:00
/*
* The following call is needed to push the
* reply data back out the socket after async
* return . Plus it frees smb1req .
*/
smb_request_done ( smb1req ) ;
END_PROFILE ( SMBtdis ) ;
}
1996-05-04 11:50:46 +04:00
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a echo .
2006-06-20 06:38:28 +04:00
conn POINTER CAN BE NULL HERE !
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2008-01-05 02:37:24 +03:00
void reply_echo ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
2007-08-05 00:08:35 +04:00
int smb_reverb ;
1998-08-14 21:38:29 +04:00
int seq_num ;
2007-08-05 00:08:35 +04:00
2000-10-06 07:21:49 +04:00
START_PROFILE ( SMBecho ) ;
2000-04-27 20:53:31 +04:00
2007-08-05 00:08:35 +04:00
if ( req - > wct < 1 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBecho ) ;
return ;
}
2008-11-02 14:20:47 +03:00
smb_reverb = SVAL ( req - > vwv + 0 , 0 ) ;
2007-08-05 00:08:35 +04:00
2022-04-05 05:53:20 +03:00
reply_smb1_outbuf ( req , 1 , req - > buflen ) ;
2007-08-05 00:08:35 +04:00
1998-08-14 21:38:29 +04:00
/* copy any incoming data back out */
2008-11-01 18:24:42 +03:00
if ( req - > buflen > 0 ) {
2008-11-01 19:35:48 +03:00
memcpy ( smb_buf ( req - > outbuf ) , req - > buf , req - > buflen ) ;
2007-08-05 00:08:35 +04:00
}
1996-05-04 11:50:46 +04:00
1998-08-14 21:38:29 +04:00
if ( smb_reverb > 100 ) {
DEBUG ( 0 , ( " large reverb (%d)?? Setting to 100 \n " , smb_reverb ) ) ;
smb_reverb = 100 ;
}
1996-05-04 11:50:46 +04:00
2009-02-17 07:45:45 +03:00
for ( seq_num = 1 ; seq_num < = smb_reverb ; seq_num + + ) {
2007-08-05 00:08:35 +04:00
SSVAL ( req - > outbuf , smb_vwv0 , seq_num ) ;
1996-05-04 11:50:46 +04:00
2007-08-05 00:08:35 +04:00
show_msg ( ( char * ) req - > outbuf ) ;
2022-03-31 22:09:13 +03:00
if ( ! smb1_srv_send ( req - > xconn ,
2023-06-05 16:45:35 +03:00
( char * ) req - > outbuf ,
true ,
req - > seqnum + 1 ,
IS_CONN_ENCRYPTED ( conn ) | | req - > encrypted ) )
2022-03-31 22:09:13 +03:00
exit_server_cleanly ( " reply_echo: smb1_srv_send failed. " ) ;
1998-08-14 21:38:29 +04:00
}
1996-05-04 11:50:46 +04:00
1998-08-14 21:38:29 +04:00
DEBUG ( 3 , ( " echo %d times \n " , smb_reverb ) ) ;
1996-05-04 11:50:46 +04:00
2007-08-05 00:08:35 +04:00
TALLOC_FREE ( req - > outbuf ) ;
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBecho ) ;
2007-08-05 00:08:35 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a printopen .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2008-01-05 02:37:24 +03:00
void reply_printopen ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
1998-08-14 21:38:29 +04:00
files_struct * fsp ;
2006-07-11 22:01:26 +04:00
NTSTATUS status ;
2008-10-19 17:30:12 +04:00
2000-10-06 07:21:49 +04:00
START_PROFILE ( SMBsplopen ) ;
2007-08-14 23:45:24 +04:00
if ( req - > wct < 2 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBsplopen ) ;
return ;
}
2000-10-06 07:21:49 +04:00
if ( ! CAN_PRINT ( conn ) ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_ACCESS_DENIED ) ;
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBsplopen ) ;
2007-08-14 23:45:24 +04:00
return ;
2000-10-06 07:21:49 +04:00
}
1996-05-04 11:50:46 +04:00
2008-11-21 23:14:53 +03:00
status = file_new ( req , conn , & fsp ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
reply_nterror ( req , status ) ;
END_PROFILE ( SMBsplopen ) ;
return ;
}
1998-08-14 21:38:29 +04:00
/* Open for exclusive use, write only. */
2010-05-04 12:28:48 +04:00
status = print_spool_open ( fsp , NULL , req - > vuid ) ;
1996-05-04 11:50:46 +04:00
2006-07-11 22:01:26 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2009-06-04 14:46:30 +04:00
file_free ( req , fsp ) ;
2007-08-14 23:45:24 +04:00
reply_nterror ( req , status ) ;
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBsplopen ) ;
2007-08-14 23:45:24 +04:00
return ;
1998-08-14 21:38:29 +04:00
}
1996-05-04 11:50:46 +04:00
2022-04-05 05:53:20 +03:00
reply_smb1_outbuf ( req , 1 , 0 ) ;
2007-08-14 23:45:24 +04:00
SSVAL ( req - > outbuf , smb_vwv0 , fsp - > fnum ) ;
2008-10-19 17:30:12 +04:00
2012-06-14 15:10:33 +04:00
DEBUG ( 3 , ( " openprint fd=%d %s \n " ,
2020-09-26 22:52:52 +03:00
fsp_get_io_fd ( fsp ) , fsp_fnum_dbg ( fsp ) ) ) ;
1998-08-01 02:39:15 +04:00
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBsplopen ) ;
2007-08-14 23:45:24 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a printclose .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-12-04 02:57:45 +03:00
2008-01-05 02:37:24 +03:00
void reply_printclose ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
2007-08-14 23:45:24 +04:00
files_struct * fsp ;
2007-02-07 00:05:34 +03:00
NTSTATUS status ;
2007-08-14 23:45:24 +04:00
2000-10-06 07:21:49 +04:00
START_PROFILE ( SMBsplclose ) ;
1996-05-04 11:50:46 +04:00
2008-03-26 20:33:38 +03:00
if ( req - > wct < 1 ) {
2007-08-14 23:45:24 +04:00
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBsplclose ) ;
return ;
}
2008-11-02 14:20:47 +03:00
fsp = file_fsp ( req , SVAL ( req - > vwv + 0 , 0 ) ) ;
2007-08-14 23:45:24 +04:00
2008-06-19 18:31:59 +04:00
if ( ! check_fsp ( conn , req , fsp ) ) {
2007-08-14 23:45:24 +04:00
END_PROFILE ( SMBsplclose ) ;
return ;
}
1996-05-04 11:50:46 +04:00
2000-10-06 07:21:49 +04:00
if ( ! CAN_PRINT ( conn ) ) {
2009-12-21 22:16:38 +03:00
reply_force_doserror ( req , ERRSRV , ERRerror ) ;
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBsplclose ) ;
2007-08-14 23:45:24 +04:00
return ;
2000-10-06 07:21:49 +04:00
}
2008-10-19 17:30:12 +04:00
2012-06-14 15:10:33 +04:00
DEBUG ( 3 , ( " printclose fd=%d %s \n " ,
2020-09-26 22:52:52 +03:00
fsp_get_io_fd ( fsp ) , fsp_fnum_dbg ( fsp ) ) ) ;
2008-10-19 17:30:12 +04:00
2022-02-01 19:47:29 +03:00
status = close_file_free ( req , & fsp , NORMAL_CLOSE ) ;
1999-12-13 16:27:58 +03:00
2007-02-07 00:05:34 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-14 23:45:24 +04:00
reply_nterror ( req , status ) ;
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBsplclose ) ;
2007-08-14 23:45:24 +04:00
return ;
1999-12-13 16:27:58 +03:00
}
1998-04-16 23:23:10 +04:00
2022-04-05 05:53:20 +03:00
reply_smb1_outbuf ( req , 0 , 0 ) ;
2008-08-14 02:46:35 +04:00
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBsplclose ) ;
2007-08-14 23:45:24 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a printqueue .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2008-01-05 02:37:24 +03:00
void reply_printqueue ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2019-11-07 13:01:05 +03:00
const struct loadparm_substitution * lp_sub =
loadparm_s3_global_substitution ( ) ;
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
2007-08-14 23:45:24 +04:00
int max_count ;
int start_index ;
2000-10-06 07:21:49 +04:00
START_PROFILE ( SMBsplretq ) ;
1998-08-14 21:38:29 +04:00
2007-08-14 23:45:24 +04:00
if ( req - > wct < 2 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBsplretq ) ;
return ;
}
2008-11-02 14:20:47 +03:00
max_count = SVAL ( req - > vwv + 0 , 0 ) ;
start_index = SVAL ( req - > vwv + 1 , 0 ) ;
2007-08-14 23:45:24 +04:00
1998-08-14 21:38:29 +04:00
/* we used to allow the client to get the cnum wrong, but that
is really quite gross and only worked when there was only
one printer - I think we should now only accept it if they
get it right ( tridge ) */
2000-10-06 07:21:49 +04:00
if ( ! CAN_PRINT ( conn ) ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_ACCESS_DENIED ) ;
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBsplretq ) ;
2007-08-14 23:45:24 +04:00
return ;
2000-10-06 07:21:49 +04:00
}
1998-08-14 21:38:29 +04:00
2022-04-05 05:53:20 +03:00
reply_smb1_outbuf ( req , 2 , 3 ) ;
2007-08-14 23:45:24 +04:00
SSVAL ( req - > outbuf , smb_vwv0 , 0 ) ;
SSVAL ( req - > outbuf , smb_vwv1 , 0 ) ;
SCVAL ( smb_buf ( req - > outbuf ) , 0 , 1 ) ;
SSVAL ( smb_buf ( req - > outbuf ) , 1 , 0 ) ;
2008-10-19 17:30:12 +04:00
1998-08-14 21:38:29 +04:00
DEBUG ( 3 , ( " printqueue start_index=%d max_count=%d \n " ,
start_index , max_count ) ) ;
1996-05-04 11:50:46 +04:00
1998-08-14 21:38:29 +04:00
{
2010-05-07 13:03:32 +04:00
TALLOC_CTX * mem_ctx = talloc_tos ( ) ;
NTSTATUS status ;
WERROR werr ;
2019-11-07 13:01:05 +03:00
const char * sharename = lp_servicename ( mem_ctx , lp_sub , SNUM ( conn ) ) ;
2010-05-07 13:03:32 +04:00
struct rpc_pipe_client * cli = NULL ;
2011-01-15 13:53:11 +03:00
struct dcerpc_binding_handle * b = NULL ;
2010-05-07 13:03:32 +04:00
struct policy_handle handle ;
struct spoolss_DevmodeContainer devmode_ctr ;
union spoolss_JobInfo * info ;
uint32_t count ;
uint32_t num_to_get ;
uint32_t first ;
uint32_t i ;
ZERO_STRUCT ( handle ) ;
2017-07-10 12:29:58 +03:00
status = rpc_pipe_open_interface ( mem_ctx ,
2013-05-17 18:44:05 +04:00
& ndr_table_spoolss ,
2011-02-21 12:25:52 +03:00
conn - > session_info ,
2011-06-07 19:21:28 +04:00
conn - > sconn - > remote_address ,
2017-02-24 03:29:12 +03:00
conn - > sconn - > local_address ,
2010-07-06 19:33:15 +04:00
conn - > sconn - > msg_ctx ,
& cli ) ;
2010-05-07 13:03:32 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " reply_printqueue: "
" could not connect to spoolss: %s \n " ,
nt_errstr ( status ) ) ) ;
reply_nterror ( req , status ) ;
goto out ;
}
2011-01-15 13:53:11 +03:00
b = cli - > binding_handle ;
2010-05-07 13:03:32 +04:00
ZERO_STRUCT ( devmode_ctr ) ;
2011-01-15 13:53:11 +03:00
status = dcerpc_spoolss_OpenPrinter ( b , mem_ctx ,
2010-05-07 13:03:32 +04:00
sharename ,
NULL , devmode_ctr ,
SEC_FLAG_MAXIMUM_ALLOWED ,
& handle ,
& werr ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
reply_nterror ( req , status ) ;
goto out ;
}
if ( ! W_ERROR_IS_OK ( werr ) ) {
reply_nterror ( req , werror_to_ntstatus ( werr ) ) ;
goto out ;
}
werr = rpccli_spoolss_enumjobs ( cli , mem_ctx ,
& handle ,
0 , /* firstjob */
0xff , /* numjobs */
2 , /* level */
0 , /* offered */
& count ,
& info ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
reply_nterror ( req , werror_to_ntstatus ( werr ) ) ;
goto out ;
}
if ( max_count > 0 ) {
first = start_index ;
} else {
first = start_index + max_count + 1 ;
}
2008-10-19 17:30:12 +04:00
2010-05-07 13:03:32 +04:00
if ( first > = count ) {
num_to_get = first ;
} else {
num_to_get = first + MIN ( ABS ( max_count ) , count - first ) ;
}
1996-05-04 11:50:46 +04:00
2010-05-07 13:03:32 +04:00
for ( i = first ; i < num_to_get ; i + + ) {
2007-08-14 23:45:24 +04:00
char blob [ 28 ] ;
char * p = blob ;
2010-05-07 13:03:32 +04:00
time_t qtime = spoolss_Time_to_time_t ( & info [ i ] . info2 . submitted ) ;
int qstatus ;
2014-08-26 04:11:58 +04:00
size_t len = 0 ;
2010-05-07 13:03:32 +04:00
uint16_t qrapjobid = pjobid_to_rap ( sharename ,
info [ i ] . info2 . job_id ) ;
2007-08-14 23:45:24 +04:00
2010-05-07 13:03:32 +04:00
if ( info [ i ] . info2 . status = = JOB_STATUS_PRINTING ) {
qstatus = 2 ;
} else {
qstatus = 3 ;
}
srv_put_dos_date2 ( p , 0 , qtime ) ;
SCVAL ( p , 4 , qstatus ) ;
SSVAL ( p , 5 , qrapjobid ) ;
SIVAL ( p , 7 , info [ i ] . info2 . size ) ;
SCVAL ( p , 11 , 0 ) ;
2014-08-26 04:11:58 +04:00
status = srvstr_push ( blob , req - > flags2 , p + 12 ,
info [ i ] . info2 . notify_name , 16 , STR_ASCII , & len ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
reply_nterror ( req , status ) ;
goto out ;
}
2007-08-14 23:45:24 +04:00
if ( message_push_blob (
& req - > outbuf ,
data_blob_const (
blob , sizeof ( blob ) ) ) = = - 1 ) {
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
2010-05-07 13:03:32 +04:00
goto out ;
2007-08-14 23:45:24 +04:00
}
1998-08-14 21:38:29 +04:00
}
1996-05-04 11:50:46 +04:00
1998-08-14 21:38:29 +04:00
if ( count > 0 ) {
2007-08-14 23:45:24 +04:00
SSVAL ( req - > outbuf , smb_vwv0 , count ) ;
SSVAL ( req - > outbuf , smb_vwv1 ,
( max_count > 0 ? first + count : first - 1 ) ) ;
SCVAL ( smb_buf ( req - > outbuf ) , 0 , 1 ) ;
SSVAL ( smb_buf ( req - > outbuf ) , 1 , 28 * count ) ;
1998-08-14 21:38:29 +04:00
}
1996-05-04 11:50:46 +04:00
2008-10-19 17:30:12 +04:00
2010-05-07 13:03:32 +04:00
DEBUG ( 3 , ( " %u entries returned in queue \n " ,
( unsigned ) count ) ) ;
out :
2011-01-15 13:53:11 +03:00
if ( b & & is_valid_policy_hnd ( & handle ) ) {
dcerpc_spoolss_ClosePrinter ( b , mem_ctx , & handle , & werr ) ;
2010-05-07 13:03:32 +04:00
}
1998-08-14 21:38:29 +04:00
}
2008-10-19 17:30:12 +04:00
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBsplretq ) ;
2007-08-14 23:45:24 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a printwrite .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
2008-01-05 02:37:24 +03:00
void reply_printwrite ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
2002-12-04 02:57:45 +03:00
int numtowrite ;
2008-11-01 19:35:48 +03:00
const char * data ;
2007-08-14 23:45:24 +04:00
files_struct * fsp ;
2002-12-04 02:57:45 +03:00
START_PROFILE ( SMBsplwr ) ;
2007-08-14 23:45:24 +04:00
if ( req - > wct < 1 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBsplwr ) ;
return ;
}
2008-10-19 17:30:12 +04:00
2008-11-02 14:20:47 +03:00
fsp = file_fsp ( req , SVAL ( req - > vwv + 0 , 0 ) ) ;
2007-08-14 23:45:24 +04:00
2008-06-19 18:31:59 +04:00
if ( ! check_fsp ( conn , req , fsp ) ) {
2007-08-14 23:45:24 +04:00
END_PROFILE ( SMBsplwr ) ;
return ;
}
2010-05-07 15:35:23 +04:00
if ( ! fsp - > print_file ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_ACCESS_DENIED ) ;
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBsplwr ) ;
2007-08-14 23:45:24 +04:00
return ;
2002-12-04 02:57:45 +03:00
}
1996-05-04 11:50:46 +04:00
2005-07-08 08:51:27 +04:00
if ( ! CHECK_WRITE ( fsp ) ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_ACCESS_DENIED ) ;
2007-08-14 23:45:24 +04:00
END_PROFILE ( SMBsplwr ) ;
return ;
2005-07-08 08:51:27 +04:00
}
1996-05-04 11:50:46 +04:00
2008-11-01 19:35:48 +03:00
numtowrite = SVAL ( req - > buf , 1 ) ;
2007-08-14 23:45:24 +04:00
2017-09-08 20:13:14 +03:00
/*
* This already protects us against CVE - 2017 - 12163.
*/
2008-11-01 18:24:42 +03:00
if ( req - > buflen < numtowrite + 3 ) {
2007-08-14 23:45:24 +04:00
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBsplwr ) ;
return ;
}
2008-11-01 19:35:48 +03:00
data = ( const char * ) req - > buf + 3 ;
2007-08-14 23:45:24 +04:00
2012-04-05 08:53:08 +04:00
if ( write_file ( req , fsp , data , ( off_t ) - 1 , numtowrite ) ! = numtowrite ) {
2009-07-11 05:23:00 +04:00
reply_nterror ( req , map_nt_error_from_unix ( errno ) ) ;
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBsplwr ) ;
2007-08-14 23:45:24 +04:00
return ;
2002-12-04 02:57:45 +03:00
}
2000-10-06 07:21:49 +04:00
2012-06-14 15:10:33 +04:00
DEBUG ( 3 , ( " printwrite %s num=%d \n " , fsp_fnum_dbg ( fsp ) , numtowrite ) ) ;
2007-09-11 22:31:29 +04:00
2022-04-05 05:53:20 +03:00
reply_smb1_outbuf ( req , 0 , 0 ) ;
2021-04-29 19:50:30 +03:00
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBsplwr ) ;
2007-08-14 23:45:24 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
2000-07-25 17:15:16 +04:00
/****************************************************************************
2001-08-31 02:20:02 +04:00
Reply to a mkdir .
2000-07-25 17:15:16 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-08-31 02:20:02 +04:00
2008-01-05 02:37:24 +03:00
void reply_mkdir ( struct smb_request * req )
2000-07-25 17:15:16 +04:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
2022-07-28 22:04:47 +03:00
struct files_struct * dirfsp = NULL ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
struct smb_filename * smb_dname = NULL ;
2007-09-08 00:57:01 +04:00
char * directory = NULL ;
2001-09-04 11:13:01 +04:00
NTSTATUS status ;
2016-10-13 13:42:59 +03:00
uint32_t ucf_flags ;
2022-07-28 22:04:47 +03:00
NTTIME twrp = 0 ;
2007-09-11 22:31:29 +04:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
2005-03-15 04:19:58 +03:00
2001-08-31 02:20:02 +04:00
START_PROFILE ( SMBmkdir ) ;
2007-09-11 22:31:29 +04:00
2008-11-02 02:59:03 +03:00
srvstr_get_path_req ( ctx , req , & directory , ( const char * ) req - > buf + 1 ,
STR_TERMINATE , & status ) ;
2003-10-09 03:21:36 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-07-30 15:35:39 +04:00
reply_nterror ( req , status ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2003-10-09 03:21:36 +04:00
}
2000-07-25 17:15:16 +04:00
2016-10-13 13:42:59 +03:00
ucf_flags = filename_create_ucf_flags ( req , FILE_CREATE ) ;
2022-07-28 22:04:47 +03:00
if ( ucf_flags & UCF_GMT_PATHNAME ) {
2022-08-04 20:02:15 +03:00
extract_snapshot_token ( directory , & twrp ) ;
2022-07-28 22:04:47 +03:00
}
2023-03-30 17:04:31 +03:00
status = smb1_strip_dfs_path ( ctx , & ucf_flags , & directory ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
reply_nterror ( req , status ) ;
goto out ;
}
2022-07-28 22:04:47 +03:00
status = filename_convert_dirfsp ( ctx ,
conn ,
directory ,
ucf_flags ,
twrp ,
& dirfsp ,
& smb_dname ) ;
2007-03-12 20:55:24 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
if ( NT_STATUS_EQUAL ( status , NT_STATUS_PATH_NOT_COVERED ) ) {
2007-07-30 15:35:39 +04:00
reply_botherror ( req , NT_STATUS_PATH_NOT_COVERED ,
ERRSRV , ERRbadpath ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2007-03-12 20:55:24 +03:00
}
2007-07-30 15:35:39 +04:00
reply_nterror ( req , status ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2007-03-08 01:12:58 +03:00
}
2002-08-17 19:27:10 +04:00
2022-07-28 22:04:47 +03:00
status = create_directory ( conn , req , dirfsp , smb_dname ) ;
2006-12-19 19:36:54 +03:00
2006-12-29 00:34:31 +03:00
DEBUG ( 5 , ( " create_directory returned %s \n " , nt_errstr ( status ) ) ) ;
2005-04-02 03:11:28 +04:00
2003-10-09 03:21:36 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2006-07-11 22:01:26 +04:00
2006-12-24 14:13:32 +03:00
if ( ! use_nt_status ( )
& & NT_STATUS_EQUAL ( status ,
NT_STATUS_OBJECT_NAME_COLLISION ) ) {
2006-07-11 22:01:26 +04:00
/*
* Yes , in the DOS error code case we get a
* ERRDOS : ERRnoaccess here . See BASE - SAMBA3ERROR
* samba4 torture test .
*/
status = NT_STATUS_DOS ( ERRDOS , ERRnoaccess ) ;
}
2007-07-30 15:35:39 +04:00
reply_nterror ( req , status ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2003-10-09 03:21:36 +04:00
}
2001-09-04 11:13:01 +04:00
2022-04-05 05:53:20 +03:00
reply_smb1_outbuf ( req , 0 , 0 ) ;
1998-08-01 02:39:15 +04:00
2009-06-10 21:37:57 +04:00
DEBUG ( 3 , ( " mkdir %s \n " , smb_dname - > base_name ) ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
out :
2009-05-25 00:13:07 +04:00
TALLOC_FREE ( smb_dname ) ;
2001-08-31 02:20:02 +04:00
END_PROFILE ( SMBmkdir ) ;
2007-07-30 15:35:39 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
1999-12-13 16:27:58 +03:00
/****************************************************************************
Reply to a rmdir .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
2008-01-05 02:37:24 +03:00
void reply_rmdir ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
struct smb_filename * smb_dname = NULL ;
2007-09-08 00:57:01 +04:00
char * directory = NULL ;
2003-10-09 03:21:36 +04:00
NTSTATUS status ;
2007-09-11 22:31:29 +04:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
2022-07-27 22:29:18 +03:00
struct files_struct * dirfsp = NULL ;
2009-12-04 00:01:10 +03:00
files_struct * fsp = NULL ;
int info = 0 ;
2022-07-27 22:29:18 +03:00
NTTIME twrp = 0 ;
2017-05-18 22:08:00 +03:00
uint32_t ucf_flags = ucf_flags_from_smb_request ( req ) ;
2007-09-11 22:31:29 +04:00
2002-12-04 02:57:45 +03:00
START_PROFILE ( SMBrmdir ) ;
2008-11-02 02:59:03 +03:00
srvstr_get_path_req ( ctx , req , & directory , ( const char * ) req - > buf + 1 ,
STR_TERMINATE , & status ) ;
2003-10-09 03:21:36 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-07-30 18:07:29 +04:00
reply_nterror ( req , status ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2003-10-09 03:21:36 +04:00
}
2002-12-04 02:57:45 +03:00
2022-07-27 22:29:18 +03:00
if ( ucf_flags & UCF_GMT_PATHNAME ) {
2022-08-04 20:02:15 +03:00
extract_snapshot_token ( directory , & twrp ) ;
2022-07-27 22:29:18 +03:00
}
2023-03-30 17:05:04 +03:00
status = smb1_strip_dfs_path ( ctx , & ucf_flags , & directory ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
reply_nterror ( req , status ) ;
goto out ;
}
2022-07-27 22:29:18 +03:00
status = filename_convert_dirfsp ( ctx ,
conn ,
directory ,
ucf_flags ,
twrp ,
& dirfsp ,
& smb_dname ) ;
2007-03-12 20:55:24 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
if ( NT_STATUS_EQUAL ( status , NT_STATUS_PATH_NOT_COVERED ) ) {
2007-07-30 18:07:29 +04:00
reply_botherror ( req , NT_STATUS_PATH_NOT_COVERED ,
ERRSRV , ERRbadpath ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2007-03-12 20:55:24 +03:00
}
2007-07-30 18:07:29 +04:00
reply_nterror ( req , status ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2002-12-04 02:57:45 +03:00
}
2007-01-16 23:49:51 +03:00
2009-12-04 00:01:10 +03:00
status = SMB_VFS_CREATE_FILE (
conn , /* conn */
req , /* req */
2022-07-27 22:29:18 +03:00
dirfsp , /* dirfsp */
2009-12-04 00:01:10 +03:00
smb_dname , /* fname */
DELETE_ACCESS , /* access_mask */
( FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
FILE_SHARE_DELETE ) ,
FILE_OPEN , /* create_disposition*/
FILE_DIRECTORY_FILE , /* create_options */
FILE_ATTRIBUTE_DIRECTORY , /* file_attributes */
0 , /* oplock_request */
2013-08-21 17:56:14 +04:00
NULL , /* lease */
2009-12-04 00:01:10 +03:00
0 , /* allocation_size */
2010-03-06 02:10:30 +03:00
0 , /* private_flags */
2009-12-04 00:01:10 +03:00
NULL , /* sd */
NULL , /* ea_list */
& fsp , /* result */
2014-11-26 16:12:51 +03:00
& info , /* pinfo */
NULL , NULL ) ; /* create context */
2009-12-04 00:01:10 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2014-09-16 08:55:39 +04:00
if ( open_was_deferred ( req - > xconn , req - > mid ) ) {
2009-12-04 00:01:10 +03:00
/* We have re-scheduled this call. */
goto out ;
}
2019-07-30 15:54:40 +03:00
if ( NT_STATUS_EQUAL ( status , NT_STATUS_SHARING_VIOLATION ) ) {
bool ok = defer_smb1_sharing_violation ( req ) ;
if ( ok ) {
goto out ;
}
}
2009-12-04 00:01:10 +03:00
reply_nterror ( req , status ) ;
goto out ;
}
status = can_set_delete_on_close ( fsp , FILE_ATTRIBUTE_DIRECTORY ) ;
2007-02-07 00:05:34 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2022-02-01 19:47:29 +03:00
close_file_free ( req , & fsp , ERROR_CLOSE ) ;
2007-07-30 18:07:29 +04:00
reply_nterror ( req , status ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2002-12-04 02:57:45 +03:00
}
2007-09-13 01:48:20 +04:00
2012-04-05 01:54:02 +04:00
if ( ! set_delete_on_close ( fsp , true ,
conn - > session_info - > security_token ,
conn - > session_info - > unix_token ) ) {
2022-02-01 19:47:29 +03:00
close_file_free ( req , & fsp , ERROR_CLOSE ) ;
2009-12-04 00:01:10 +03:00
reply_nterror ( req , NT_STATUS_ACCESS_DENIED ) ;
goto out ;
}
2022-02-01 19:47:29 +03:00
status = close_file_free ( req , & fsp , NORMAL_CLOSE ) ;
2010-01-13 03:50:40 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
reply_nterror ( req , status ) ;
} else {
2022-04-05 05:53:20 +03:00
reply_smb1_outbuf ( req , 0 , 0 ) ;
2010-01-13 03:50:40 +03:00
}
2007-09-13 01:48:20 +04:00
2009-07-09 07:15:02 +04:00
DEBUG ( 3 , ( " rmdir %s \n " , smb_fname_str_dbg ( smb_dname ) ) ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
out :
2009-05-25 00:13:07 +04:00
TALLOC_FREE ( smb_dname ) ;
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBrmdir ) ;
2007-07-30 18:07:29 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
1998-07-11 04:28:34 +04:00
/****************************************************************************
Reply to a mv .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-01-05 02:37:24 +03:00
void reply_mv ( struct smb_request * req )
1998-07-11 04:28:34 +04:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
2007-09-11 22:31:29 +04:00
char * name = NULL ;
char * newname = NULL ;
2008-11-01 19:35:48 +03:00
const char * p ;
2015-04-27 02:02:55 +03:00
uint32_t attrs ;
2001-09-04 11:13:01 +04:00
NTSTATUS status ;
2007-09-11 22:31:29 +04:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
2022-07-28 22:09:34 +03:00
struct files_struct * src_dirfsp = NULL ;
2009-07-24 22:39:56 +04:00
struct smb_filename * smb_fname_src = NULL ;
2022-07-28 22:09:34 +03:00
struct files_struct * dst_dirfsp = NULL ;
2009-07-24 22:39:56 +04:00
struct smb_filename * smb_fname_dst = NULL ;
2020-03-27 01:51:18 +03:00
const char * dst_original_lcomp = NULL ;
2021-12-02 00:56:31 +03:00
uint32_t src_ucf_flags = ucf_flags_from_smb_request ( req ) ;
2022-07-28 22:09:34 +03:00
NTTIME src_twrp = 0 ;
2021-12-02 00:56:31 +03:00
uint32_t dst_ucf_flags = ucf_flags_from_smb_request ( req ) ;
2022-07-28 22:09:34 +03:00
NTTIME dst_twrp = 0 ;
2011-01-21 03:27:56 +03:00
bool stream_rename = false ;
2000-03-09 01:14:30 +03:00
2001-09-04 11:13:01 +04:00
START_PROFILE ( SMBmv ) ;
1998-07-11 04:28:34 +04:00
2007-08-14 18:50:49 +04:00
if ( req - > wct < 1 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
2009-07-24 22:39:56 +04:00
goto out ;
2007-08-14 18:50:49 +04:00
}
2007-07-05 20:26:27 +04:00
2008-11-02 14:20:47 +03:00
attrs = SVAL ( req - > vwv + 0 , 0 ) ;
2007-08-14 18:50:49 +04:00
2008-11-01 19:35:48 +03:00
p = ( const char * ) req - > buf + 1 ;
2020-09-29 23:09:52 +03:00
p + = srvstr_get_path_req ( ctx , req , & name , p , STR_TERMINATE ,
& status ) ;
2003-10-09 03:21:36 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-14 18:50:49 +04:00
reply_nterror ( req , status ) ;
2009-07-24 22:39:56 +04:00
goto out ;
2003-10-09 03:21:36 +04:00
}
2001-09-04 11:13:01 +04:00
p + + ;
2020-09-29 23:09:52 +03:00
p + = srvstr_get_path_req ( ctx , req , & newname , p , STR_TERMINATE ,
& status ) ;
2003-10-09 03:21:36 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-14 18:50:49 +04:00
reply_nterror ( req , status ) ;
2009-07-24 22:39:56 +04:00
goto out ;
2003-10-09 03:21:36 +04:00
}
2007-09-11 22:31:29 +04:00
2015-12-23 00:41:45 +03:00
if ( ! req - > posix_pathnames ) {
2011-01-21 03:27:56 +03:00
/* The newname must begin with a ':' if the
name contains a ' : ' . */
if ( strchr_m ( name , ' : ' ) ) {
if ( newname [ 0 ] ! = ' : ' ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
goto out ;
}
stream_rename = true ;
}
}
2022-07-28 22:09:34 +03:00
if ( src_ucf_flags & UCF_GMT_PATHNAME ) {
2022-08-04 20:02:15 +03:00
extract_snapshot_token ( name , & src_twrp ) ;
2022-07-28 22:09:34 +03:00
}
2023-03-30 17:06:04 +03:00
status = smb1_strip_dfs_path ( ctx , & src_ucf_flags , & name ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
reply_nterror ( req , status ) ;
goto out ;
}
2022-07-28 22:09:34 +03:00
status = filename_convert_dirfsp ( ctx ,
conn ,
name ,
src_ucf_flags ,
src_twrp ,
& src_dirfsp ,
& smb_fname_src ) ;
2009-07-24 22:39:56 +04:00
2007-03-12 20:55:24 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
if ( NT_STATUS_EQUAL ( status , NT_STATUS_PATH_NOT_COVERED ) ) {
2007-08-14 18:50:49 +04:00
reply_botherror ( req , NT_STATUS_PATH_NOT_COVERED ,
ERRSRV , ERRbadpath ) ;
2009-07-24 22:39:56 +04:00
goto out ;
2007-03-12 20:55:24 +03:00
}
2007-08-14 18:50:49 +04:00
reply_nterror ( req , status ) ;
2009-07-24 22:39:56 +04:00
goto out ;
2007-03-08 01:12:58 +03:00
}
2007-03-12 20:55:24 +03:00
2022-07-28 22:09:34 +03:00
if ( dst_ucf_flags & UCF_GMT_PATHNAME ) {
2022-08-04 20:02:15 +03:00
extract_snapshot_token ( newname , & dst_twrp ) ;
2022-07-28 22:09:34 +03:00
}
2023-03-30 17:06:44 +03:00
status = smb1_strip_dfs_path ( ctx , & dst_ucf_flags , & newname ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
reply_nterror ( req , status ) ;
goto out ;
}
2022-07-28 22:09:34 +03:00
status = filename_convert_dirfsp ( ctx ,
conn ,
newname ,
dst_ucf_flags ,
dst_twrp ,
& dst_dirfsp ,
& smb_fname_dst ) ;
2009-07-24 22:39:56 +04:00
2007-03-12 20:55:24 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
if ( NT_STATUS_EQUAL ( status , NT_STATUS_PATH_NOT_COVERED ) ) {
2007-08-14 18:50:49 +04:00
reply_botherror ( req , NT_STATUS_PATH_NOT_COVERED ,
ERRSRV , ERRbadpath ) ;
2009-07-24 22:39:56 +04:00
goto out ;
2007-03-12 20:55:24 +03:00
}
2007-08-14 18:50:49 +04:00
reply_nterror ( req , status ) ;
2009-07-24 22:39:56 +04:00
goto out ;
2007-03-08 01:12:58 +03:00
}
2007-09-11 22:31:29 +04:00
2020-03-27 01:51:18 +03:00
/* Get the last component of the destination for rename_internals(). */
dst_original_lcomp = get_original_lcomp ( ctx ,
conn ,
newname ,
dst_ucf_flags ) ;
if ( dst_original_lcomp = = NULL ) {
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
goto out ;
}
2011-01-21 03:27:56 +03:00
if ( stream_rename ) {
/* smb_fname_dst->base_name must be the same as
smb_fname_src - > base_name . */
TALLOC_FREE ( smb_fname_dst - > base_name ) ;
smb_fname_dst - > base_name = talloc_strdup ( smb_fname_dst ,
smb_fname_src - > base_name ) ;
if ( ! smb_fname_dst - > base_name ) {
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
goto out ;
}
}
2009-07-24 22:39:56 +04:00
DEBUG ( 3 , ( " reply_mv : %s -> %s \n " , smb_fname_str_dbg ( smb_fname_src ) ,
smb_fname_str_dbg ( smb_fname_dst ) ) ) ;
2007-09-11 22:31:29 +04:00
2020-03-25 23:42:34 +03:00
status = rename_internals ( ctx ,
conn ,
req ,
2022-07-28 22:09:34 +03:00
src_dirfsp , /* src_dirfsp */
2020-03-25 23:42:34 +03:00
smb_fname_src ,
smb_fname_dst ,
2020-03-27 01:51:18 +03:00
dst_original_lcomp ,
2020-03-25 23:42:34 +03:00
attrs ,
false ,
DELETE_ACCESS ) ;
2001-09-04 11:13:01 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2014-09-16 08:55:39 +04:00
if ( open_was_deferred ( req - > xconn , req - > mid ) ) {
2004-06-08 20:14:31 +04:00
/* We have re-scheduled this call. */
2009-07-24 22:39:56 +04:00
goto out ;
2004-06-08 20:14:31 +04:00
}
2019-07-30 15:54:40 +03:00
if ( NT_STATUS_EQUAL ( status , NT_STATUS_SHARING_VIOLATION ) ) {
bool ok = defer_smb1_sharing_violation ( req ) ;
if ( ok ) {
goto out ;
}
}
2007-08-14 18:50:49 +04:00
reply_nterror ( req , status ) ;
2009-07-24 22:39:56 +04:00
goto out ;
2001-09-04 11:13:01 +04:00
}
2000-09-20 23:00:21 +04:00
2022-04-05 05:53:20 +03:00
reply_smb1_outbuf ( req , 0 , 0 ) ;
2009-07-24 22:39:56 +04:00
out :
TALLOC_FREE ( smb_fname_src ) ;
TALLOC_FREE ( smb_fname_dst ) ;
2001-09-04 11:13:01 +04:00
END_PROFILE ( SMBmv ) ;
2007-08-14 18:50:49 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a file copy .
2021-12-01 23:24:07 +03:00
From MS - CIFS .
This command was introduced in the LAN Manager 1.0 dialect
It was rendered obsolete in the NT LAN Manager dialect .
This command was used to perform server - side file copies , but
is no longer used . Clients SHOULD
NOT send requests using this command code .
Servers receiving requests with this command code
SHOULD return STATUS_NOT_IMPLEMENTED ( ERRDOS / ERRbadfunc ) .
2002-09-25 19:19:00 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-01-05 02:37:24 +03:00
void reply_copy ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2002-12-04 02:57:45 +03:00
START_PROFILE ( SMBcopy ) ;
2021-12-01 23:24:07 +03:00
reply_nterror ( req , NT_STATUS_NOT_IMPLEMENTED ) ;
2002-12-04 02:57:45 +03:00
END_PROFILE ( SMBcopy ) ;
2007-08-15 01:21:52 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
2005-04-27 22:32:37 +04:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_LOCKING
2001-07-02 06:42:41 +04:00
/****************************************************************************
Get a lock pid , dealing with large count requests .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-05-07 17:20:50 +04:00
uint64_t get_lock_pid ( const uint8_t * data , int data_offset ,
2008-11-01 19:22:15 +03:00
bool large_file_format )
2001-07-02 06:42:41 +04:00
{
if ( ! large_file_format )
2010-05-07 17:20:50 +04:00
return ( uint64_t ) SVAL ( data , SMB_LPID_OFFSET ( data_offset ) ) ;
2001-07-02 06:42:41 +04:00
else
2010-05-07 17:20:50 +04:00
return ( uint64_t ) SVAL ( data , SMB_LARGE_LPID_OFFSET ( data_offset ) ) ;
2001-07-02 06:42:41 +04:00
}
1999-12-13 16:27:58 +03:00
/****************************************************************************
Get a lock count , dealing with large count requests .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-11-01 19:22:15 +03:00
uint64_t get_lock_count ( const uint8_t * data , int data_offset ,
bool large_file_format )
1999-12-13 16:27:58 +03:00
{
2008-10-14 03:59:36 +04:00
uint64_t count = 0 ;
1999-12-13 16:27:58 +03:00
2002-12-04 02:57:45 +03:00
if ( ! large_file_format ) {
2008-10-14 03:59:36 +04:00
count = ( uint64_t ) IVAL ( data , SMB_LKLEN_OFFSET ( data_offset ) ) ;
2002-12-04 02:57:45 +03:00
} else {
2014-07-15 14:55:21 +04:00
/*
* No BVAL , this is reversed !
*/
2008-10-14 03:59:36 +04:00
count = ( ( ( uint64_t ) IVAL ( data , SMB_LARGE_LKLEN_OFFSET_HIGH ( data_offset ) ) ) < < 32 ) |
( ( uint64_t ) IVAL ( data , SMB_LARGE_LKLEN_OFFSET_LOW ( data_offset ) ) ) ;
2002-12-04 02:57:45 +03:00
}
2000-04-11 23:44:54 +04:00
2002-12-04 02:57:45 +03:00
return count ;
1999-12-13 16:27:58 +03:00
}
1996-05-04 11:50:46 +04:00
/****************************************************************************
2002-09-25 19:19:00 +04:00
Reply to a lockingX request .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
2019-06-13 13:58:02 +03:00
static void reply_lockingx_done ( struct tevent_req * subreq ) ;
2008-01-05 02:37:24 +03:00
void reply_lockingX ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
2007-08-14 14:27:27 +04:00
files_struct * fsp ;
unsigned char locktype ;
2019-05-30 12:39:10 +03:00
enum brl_type brltype ;
2007-08-14 14:27:27 +04:00
unsigned char oplocklevel ;
2015-04-27 02:02:55 +03:00
uint16_t num_ulocks ;
uint16_t num_locks ;
2015-05-16 00:56:25 +03:00
int32_t lock_timeout ;
2019-06-03 12:16:33 +03:00
uint16_t i ;
2008-11-01 19:35:48 +03:00
const uint8_t * data ;
2007-10-19 04:40:25 +04:00
bool large_file_format ;
2005-11-02 03:19:26 +03:00
NTSTATUS status = NT_STATUS_UNSUCCESSFUL ;
2019-05-30 12:42:16 +03:00
struct smbd_lock_element * locks = NULL ;
2019-06-13 13:59:54 +03:00
struct tevent_req * subreq = NULL ;
1999-12-13 16:27:58 +03:00
2001-08-27 12:19:43 +04:00
START_PROFILE ( SMBlockingX ) ;
2007-08-14 14:27:27 +04:00
2007-08-14 17:38:14 +04:00
if ( req - > wct < 8 ) {
2007-08-14 14:47:47 +04:00
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBlockingX ) ;
return ;
2007-08-14 14:27:27 +04:00
}
2008-10-19 17:30:12 +04:00
2008-11-02 14:20:47 +03:00
fsp = file_fsp ( req , SVAL ( req - > vwv + 2 , 0 ) ) ;
locktype = CVAL ( req - > vwv + 3 , 0 ) ;
oplocklevel = CVAL ( req - > vwv + 3 , 1 ) ;
num_ulocks = SVAL ( req - > vwv + 6 , 0 ) ;
num_locks = SVAL ( req - > vwv + 7 , 0 ) ;
lock_timeout = IVAL ( req - > vwv + 4 , 0 ) ;
2014-07-14 19:22:01 +04:00
large_file_format = ( ( locktype & LOCKING_ANDX_LARGE_FILES ) ! = 0 ) ;
2007-08-14 14:27:27 +04:00
2008-06-19 18:31:59 +04:00
if ( ! check_fsp ( conn , req , fsp ) ) {
2007-08-14 17:38:14 +04:00
END_PROFILE ( SMBlockingX ) ;
2007-08-14 14:47:47 +04:00
return ;
}
2008-10-19 17:30:12 +04:00
2008-11-01 19:35:48 +03:00
data = req - > buf ;
2002-03-11 04:34:14 +03:00
2004-10-19 02:01:10 +04:00
if ( locktype & LOCKING_ANDX_CHANGE_LOCKTYPE ) {
2002-03-11 04:34:14 +03:00
/* we don't support these - and CANCEL_LOCK makes w2k
and XP reboot so I don ' t really want to be
compatible ! ( tridge ) */
2009-12-21 22:16:38 +03:00
reply_force_doserror ( req , ERRDOS , ERRnoatomiclocks ) ;
2007-08-14 14:47:47 +04:00
END_PROFILE ( SMBlockingX ) ;
return ;
2002-03-11 04:34:14 +03:00
}
2008-10-19 17:30:12 +04:00
2001-08-27 12:19:43 +04:00
/* Check if this is an oplock break on a file
we have granted an oplock on .
*/
2014-07-14 19:19:53 +04:00
if ( locktype & LOCKING_ANDX_OPLOCK_RELEASE ) {
2001-08-27 12:19:43 +04:00
/* Client can insist on breaking to none. */
2007-10-19 04:40:25 +04:00
bool break_to_none = ( oplocklevel = = 0 ) ;
bool result ;
2005-09-30 21:13:37 +04:00
DEBUG ( 5 , ( " reply_lockingX: oplock break reply (%u) from client "
2012-06-14 15:10:33 +04:00
" for %s \n " , ( unsigned int ) oplocklevel ,
fsp_fnum_dbg ( fsp ) ) ) ;
1999-12-13 16:27:58 +03:00
2001-08-27 12:19:43 +04:00
/*
2005-09-30 21:13:37 +04:00
* Make sure we have granted an exclusive or batch oplock on
* this file .
2001-08-27 12:19:43 +04:00
*/
2008-10-19 17:30:12 +04:00
2005-09-30 21:13:37 +04:00
if ( fsp - > oplock_type = = 0 ) {
2006-04-10 22:44:27 +04:00
/* The Samba4 nbench simulator doesn't understand
the difference between break to level2 and break
to none from level2 - it sends oplock break
replies in both cases . Don ' t keep logging an error
message here - just ignore it . JRA . */
DEBUG ( 5 , ( " reply_lockingX: Error : oplock break from "
2012-06-14 15:10:33 +04:00
" client for %s (oplock=%d) and no "
2005-09-30 21:13:37 +04:00
" oplock granted on this file (%s). \n " ,
2012-06-14 15:10:33 +04:00
fsp_fnum_dbg ( fsp ) , fsp - > oplock_type ,
2009-07-11 01:50:37 +04:00
fsp_str_dbg ( fsp ) ) ) ;
2005-09-30 21:13:37 +04:00
/* if this is a pure oplock break request then don't
* send a reply */
2001-08-27 12:19:43 +04:00
if ( num_locks = = 0 & & num_ulocks = = 0 ) {
END_PROFILE ( SMBlockingX ) ;
2007-08-14 14:47:47 +04:00
return ;
2001-08-27 12:19:43 +04:00
}
2019-05-30 12:31:56 +03:00
END_PROFILE ( SMBlockingX ) ;
reply_nterror ( req , NT_STATUS_FILE_LOCK_CONFLICT ) ;
return ;
2001-08-27 12:19:43 +04:00
}
1998-09-11 05:24:30 +04:00
2005-09-30 21:13:37 +04:00
if ( ( fsp - > sent_oplock_break = = BREAK_TO_NONE_SENT ) | |
( break_to_none ) ) {
result = remove_oplock ( fsp ) ;
} else {
result = downgrade_oplock ( fsp ) ;
2001-08-27 12:19:43 +04:00
}
2008-10-19 17:30:12 +04:00
2005-09-30 21:13:37 +04:00
if ( ! result ) {
DEBUG ( 0 , ( " reply_lockingX: error in removing "
2009-07-11 01:50:37 +04:00
" oplock on file %s \n " , fsp_str_dbg ( fsp ) ) ) ;
2005-09-30 21:13:37 +04:00
/* Hmmm. Is this panic justified? */
smb_panic ( " internal tdb error " ) ;
}
/* if this is a pure oplock break request then don't send a
* reply */
2001-08-27 12:19:43 +04:00
if ( num_locks = = 0 & & num_ulocks = = 0 ) {
/* Sanity check - ensure a pure oplock break is not a
chained request . */
2014-07-14 19:20:57 +04:00
if ( CVAL ( req - > vwv + 0 , 0 ) ! = 0xff ) {
2005-09-30 21:13:37 +04:00
DEBUG ( 0 , ( " reply_lockingX: Error : pure oplock "
" break is a chained %d request ! \n " ,
2008-11-02 14:20:47 +03:00
( unsigned int ) CVAL ( req - > vwv + 0 , 0 ) ) ) ;
2014-07-14 19:20:57 +04:00
}
2001-08-27 12:19:43 +04:00
END_PROFILE ( SMBlockingX ) ;
2007-08-14 14:47:47 +04:00
return ;
2001-08-27 12:19:43 +04:00
}
}
1999-12-13 16:27:58 +03:00
2008-11-01 18:24:42 +03:00
if ( req - > buflen <
2007-08-14 17:38:14 +04:00
( num_ulocks + num_locks ) * ( large_file_format ? 20 : 10 ) ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBlockingX ) ;
return ;
}
2008-10-19 17:30:12 +04:00
2019-06-13 13:59:54 +03:00
if ( num_ulocks ! = 0 ) {
struct smbd_lock_element * ulocks = NULL ;
bool ok ;
2009-07-07 19:24:25 +04:00
2019-06-13 13:59:54 +03:00
ulocks = talloc_array (
req , struct smbd_lock_element , num_ulocks ) ;
if ( ulocks = = NULL ) {
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
END_PROFILE ( SMBlockingX ) ;
return ;
}
2008-10-19 17:30:12 +04:00
2019-06-13 13:59:54 +03:00
/*
* Data now points at the beginning of the list of
* smb_unlkrng structs
*/
for ( i = 0 ; i < num_ulocks ; i + + ) {
2019-08-08 20:26:28 +03:00
ulocks [ i ] . req_guid = smbd_request_guid ( req ,
UINT16_MAX - i ) ,
2019-06-13 13:59:54 +03:00
ulocks [ i ] . smblctx = get_lock_pid (
data , i , large_file_format ) ;
ulocks [ i ] . count = get_lock_count (
data , i , large_file_format ) ;
ulocks [ i ] . offset = get_lock_offset (
data , i , large_file_format ) ;
ulocks [ i ] . brltype = UNLOCK_LOCK ;
2021-11-17 01:26:44 +03:00
ulocks [ i ] . lock_flav = WINDOWS_LOCK ;
2019-06-13 13:59:54 +03:00
}
/*
* Unlock cancels pending locks
*/
ok = smbd_smb1_brl_finish_by_lock (
fsp ,
large_file_format ,
ulocks [ 0 ] ,
NT_STATUS_OK ) ;
if ( ok ) {
2022-04-05 05:53:20 +03:00
reply_smb1_outbuf ( req , 2 , 0 ) ;
2019-06-13 13:59:54 +03:00
SSVAL ( req - > outbuf , smb_vwv0 , 0xff ) ;
SSVAL ( req - > outbuf , smb_vwv1 , 0 ) ;
END_PROFILE ( SMBlockingX ) ;
return ;
}
status = smbd_do_unlocking (
2021-11-17 04:04:02 +03:00
req , fsp , num_ulocks , ulocks ) ;
2019-06-13 13:59:54 +03:00
TALLOC_FREE ( ulocks ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
END_PROFILE ( SMBlockingX ) ;
reply_nterror ( req , status ) ;
return ;
}
2019-05-30 12:42:16 +03:00
}
2001-08-27 12:19:43 +04:00
/* Now do any requested locks */
data + = ( ( large_file_format ? 20 : 10 ) * num_ulocks ) ;
2008-10-19 17:30:12 +04:00
2001-08-27 12:19:43 +04:00
/* Data now points at the beginning of the list
of smb_lkrng structs */
2008-10-19 17:30:12 +04:00
2019-05-30 12:39:10 +03:00
if ( locktype & LOCKING_ANDX_SHARED_LOCK ) {
2019-06-13 13:59:54 +03:00
brltype = READ_LOCK ;
2019-05-30 12:39:10 +03:00
} else {
2019-06-13 13:59:54 +03:00
brltype = WRITE_LOCK ;
2019-05-30 12:39:10 +03:00
}
2019-05-30 12:42:16 +03:00
locks = talloc_array ( req , struct smbd_lock_element , num_locks ) ;
if ( locks = = NULL ) {
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
END_PROFILE ( SMBlockingX ) ;
return ;
}
2019-06-03 12:16:33 +03:00
for ( i = 0 ; i < num_locks ; i + + ) {
2019-08-08 20:26:28 +03:00
locks [ i ] . req_guid = smbd_request_guid ( req , i ) ,
2010-05-07 17:20:50 +04:00
locks [ i ] . smblctx = get_lock_pid ( data , i , large_file_format ) ;
2009-07-07 19:24:25 +04:00
locks [ i ] . count = get_lock_count ( data , i , large_file_format ) ;
2014-07-15 13:52:07 +04:00
locks [ i ] . offset = get_lock_offset ( data , i , large_file_format ) ;
2019-05-30 12:39:10 +03:00
locks [ i ] . brltype = brltype ;
2021-11-17 01:26:44 +03:00
locks [ i ] . lock_flav = WINDOWS_LOCK ;
2001-08-27 12:19:43 +04:00
}
2008-10-19 17:30:12 +04:00
2019-05-31 13:19:25 +03:00
if ( locktype & LOCKING_ANDX_CANCEL_LOCK ) {
2019-06-13 13:59:54 +03:00
bool ok ;
2019-05-31 13:19:25 +03:00
if ( num_locks = = 0 ) {
/* See smbtorture3 lock11 test */
2022-04-05 05:53:20 +03:00
reply_smb1_outbuf ( req , 2 , 0 ) ;
2019-06-13 13:59:54 +03:00
/* andx chain ends */
SSVAL ( req - > outbuf , smb_vwv0 , 0xff ) ;
SSVAL ( req - > outbuf , smb_vwv1 , 0 ) ;
END_PROFILE ( SMBlockingX ) ;
return ;
2019-05-31 13:19:25 +03:00
}
2019-06-13 13:59:54 +03:00
ok = smbd_smb1_brl_finish_by_lock (
fsp ,
large_file_format ,
locks [ 0 ] , /* Windows only cancels the first lock */
NT_STATUS_FILE_LOCK_CONFLICT ) ;
2019-05-31 13:19:25 +03:00
2019-06-13 13:59:54 +03:00
if ( ! ok ) {
reply_force_doserror ( req , ERRDOS , ERRcancelviolation ) ;
END_PROFILE ( SMBlockingX ) ;
return ;
2019-05-31 13:19:25 +03:00
}
2022-04-05 05:53:20 +03:00
reply_smb1_outbuf ( req , 2 , 0 ) ;
2019-06-13 13:59:54 +03:00
SSVAL ( req - > outbuf , smb_vwv0 , 0xff ) ;
SSVAL ( req - > outbuf , smb_vwv1 , 0 ) ;
2019-05-31 13:19:25 +03:00
END_PROFILE ( SMBlockingX ) ;
return ;
}
2019-06-13 13:59:54 +03:00
subreq = smbd_smb1_do_locks_send (
fsp ,
req - > sconn - > ev_ctx ,
& req ,
fsp ,
lock_timeout ,
large_file_format ,
num_locks ,
locks ) ;
if ( subreq = = NULL ) {
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
2009-07-07 19:24:25 +04:00
END_PROFILE ( SMBlockingX ) ;
return ;
}
2019-06-13 13:59:54 +03:00
tevent_req_set_callback ( subreq , reply_lockingx_done , NULL ) ;
END_PROFILE ( SMBlockingX ) ;
}
1998-09-11 05:24:30 +04:00
2019-06-13 13:59:54 +03:00
static void reply_lockingx_done ( struct tevent_req * subreq )
{
struct smb_request * req = NULL ;
NTSTATUS status ;
bool ok ;
START_PROFILE ( SMBlockingX ) ;
ok = smbd_smb1_do_locks_extract_smbreq ( subreq , talloc_tos ( ) , & req ) ;
SMB_ASSERT ( ok ) ;
2008-10-19 17:30:12 +04:00
2019-06-13 13:59:54 +03:00
status = smbd_smb1_do_locks_recv ( subreq ) ;
TALLOC_FREE ( subreq ) ;
DBG_DEBUG ( " smbd_smb1_do_locks_recv returned %s \n " , nt_errstr ( status ) ) ;
if ( NT_STATUS_IS_OK ( status ) ) {
2022-04-05 05:53:20 +03:00
reply_smb1_outbuf ( req , 2 , 0 ) ;
2019-06-13 13:59:54 +03:00
SSVAL ( req - > outbuf , smb_vwv0 , 0xff ) ; /* andx chain ends */
SSVAL ( req - > outbuf , smb_vwv1 , 0 ) ; /* no andx offset */
} else {
reply_nterror ( req , status ) ;
}
2008-10-19 17:30:12 +04:00
2022-03-31 22:09:13 +03:00
ok = smb1_srv_send ( req - > xconn ,
2023-06-05 16:45:35 +03:00
( char * ) req - > outbuf ,
true ,
req - > seqnum + 1 ,
IS_CONN_ENCRYPTED ( req - > conn ) ) ;
2019-06-13 13:59:54 +03:00
if ( ! ok ) {
2022-03-31 22:09:13 +03:00
exit_server_cleanly ( " reply_lock_done: smb1_srv_send failed. " ) ;
2019-06-13 13:59:54 +03:00
}
TALLOC_FREE ( req ) ;
2000-10-06 07:21:49 +04:00
END_PROFILE ( SMBlockingX ) ;
1996-05-04 11:50:46 +04:00
}
2005-04-27 22:32:37 +04:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_ALL
1996-05-04 11:50:46 +04:00
/****************************************************************************
2001-10-19 04:56:03 +04:00
Reply to a SMBreadbmpx ( read block multiplex ) request .
2007-08-15 13:52:09 +04:00
Always reply with an error , if someone has a platform really needs this ,
please contact vl @ samba . org
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-10-19 04:56:03 +04:00
2008-01-05 02:37:24 +03:00
void reply_readbmpx ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2001-10-19 04:56:03 +04:00
START_PROFILE ( SMBreadBmpx ) ;
2009-12-21 22:16:38 +03:00
reply_force_doserror ( req , ERRSRV , ERRuseSTD ) ;
2007-08-15 13:52:09 +04:00
END_PROFILE ( SMBreadBmpx ) ;
return ;
}
1996-05-04 11:50:46 +04:00
2007-08-15 13:52:09 +04:00
/****************************************************************************
Reply to a SMBreadbs ( read block multiplex secondary ) request .
Always reply with an error , if someone has a platform really needs this ,
please contact vl @ samba . org
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1996-05-04 11:50:46 +04:00
2008-01-05 02:37:24 +03:00
void reply_readbs ( struct smb_request * req )
2007-08-15 13:52:09 +04:00
{
START_PROFILE ( SMBreadBs ) ;
2009-12-21 22:16:38 +03:00
reply_force_doserror ( req , ERRSRV , ERRuseSTD ) ;
2007-08-15 13:52:09 +04:00
END_PROFILE ( SMBreadBs ) ;
return ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
2001-10-19 04:56:03 +04:00
Reply to a SMBsetattrE .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
2008-01-05 02:37:24 +03:00
void reply_setattrE ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
2009-01-24 01:40:19 +03:00
struct smb_file_time ft ;
2007-08-15 00:55:24 +04:00
files_struct * fsp ;
2008-03-12 17:39:38 +03:00
NTSTATUS status ;
2007-08-15 00:55:24 +04:00
2002-03-20 03:46:53 +03:00
START_PROFILE ( SMBsetattrE ) ;
2019-12-02 18:30:50 +03:00
init_smb_file_time ( & ft ) ;
1996-05-04 11:50:46 +04:00
2007-08-15 00:55:24 +04:00
if ( req - > wct < 7 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
2009-07-03 00:39:20 +04:00
goto out ;
2007-08-15 00:55:24 +04:00
}
2008-11-02 14:20:47 +03:00
fsp = file_fsp ( req , SVAL ( req - > vwv + 0 , 0 ) ) ;
1996-05-04 11:50:46 +04:00
2002-03-20 03:46:53 +03:00
if ( ! fsp | | ( fsp - > conn ! = conn ) ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_INVALID_HANDLE ) ;
2009-07-03 00:39:20 +04:00
goto out ;
2002-03-20 03:46:53 +03:00
}
1996-05-04 11:50:46 +04:00
2002-03-20 03:46:53 +03:00
/*
2009-01-24 01:40:19 +03:00
* Convert the DOS times into unix times .
2002-03-20 03:46:53 +03:00
*/
2019-12-02 18:30:50 +03:00
ft . atime = time_t_to_full_timespec (
2009-01-24 01:40:19 +03:00
srv_make_unix_date2 ( req - > vwv + 3 ) ) ;
2019-12-02 18:30:50 +03:00
ft . mtime = time_t_to_full_timespec (
2009-01-24 01:40:19 +03:00
srv_make_unix_date2 ( req - > vwv + 5 ) ) ;
2019-12-02 18:30:50 +03:00
ft . create_time = time_t_to_full_timespec (
2009-01-24 01:40:19 +03:00
srv_make_unix_date2 ( req - > vwv + 1 ) ) ;
2008-10-19 17:30:12 +04:00
2022-04-05 05:53:20 +03:00
reply_smb1_outbuf ( req , 0 , 0 ) ;
2007-08-15 00:55:24 +04:00
2023-07-18 12:30:18 +03:00
/*
2002-03-20 03:46:53 +03:00
* Patch from Ray Frush < frush @ engr . colostate . edu >
* Sometimes times are sent as zero - ignore them .
*/
1997-09-23 23:19:06 +04:00
2008-03-12 17:39:38 +03:00
/* Ensure we have a valid stat struct for the source. */
2009-10-03 00:45:38 +04:00
status = vfs_stat_fsp ( fsp ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
reply_nterror ( req , status ) ;
goto out ;
2002-03-20 03:46:53 +03:00
}
1997-09-23 23:19:06 +04:00
2011-11-16 05:41:48 +04:00
if ( ! ( fsp - > access_mask & FILE_WRITE_ATTRIBUTES ) ) {
reply_nterror ( req , NT_STATUS_ACCESS_DENIED ) ;
goto out ;
}
2009-07-11 01:50:37 +04:00
status = smb_set_file_time ( conn , fsp , fsp - > fsp_name , & ft , true ) ;
2008-03-12 17:39:38 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , status ) ;
2009-07-03 00:39:20 +04:00
goto out ;
2002-03-20 03:46:53 +03:00
}
2008-10-19 17:30:12 +04:00
2020-04-02 18:37:02 +03:00
if ( fsp - > fsp_flags . modified ) {
2020-03-12 21:23:40 +03:00
trigger_write_time_update_immediate ( fsp ) ;
}
2012-06-14 15:10:33 +04:00
DEBUG ( 3 , ( " reply_setattrE %s actime=%u modtime=%u "
2009-01-24 01:40:19 +03:00
" createtime=%u \n " ,
2012-06-14 15:10:33 +04:00
fsp_fnum_dbg ( fsp ) ,
2009-01-24 01:40:19 +03:00
( unsigned int ) ft . atime . tv_sec ,
( unsigned int ) ft . mtime . tv_sec ,
( unsigned int ) ft . create_time . tv_sec
) ) ;
2009-07-03 00:39:20 +04:00
out :
2002-03-20 03:46:53 +03:00
END_PROFILE ( SMBsetattrE ) ;
2007-08-15 00:55:24 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
2001-10-19 04:56:03 +04:00
/* Back from the dead for OS/2..... JRA. */
/****************************************************************************
Reply to a SMBwritebmpx ( write block multiplex primary ) request .
2007-08-15 13:52:09 +04:00
Always reply with an error , if someone has a platform really needs this ,
please contact vl @ samba . org
2001-10-19 04:56:03 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-01-05 02:37:24 +03:00
void reply_writebmpx ( struct smb_request * req )
2001-10-19 04:56:03 +04:00
{
START_PROFILE ( SMBwriteBmpx ) ;
2009-12-21 22:16:38 +03:00
reply_force_doserror ( req , ERRSRV , ERRuseSTD ) ;
2001-10-19 04:56:03 +04:00
END_PROFILE ( SMBwriteBmpx ) ;
2007-08-15 13:52:09 +04:00
return ;
2001-10-19 04:56:03 +04:00
}
/****************************************************************************
Reply to a SMBwritebs ( write block multiplex secondary ) request .
2007-08-15 13:52:09 +04:00
Always reply with an error , if someone has a platform really needs this ,
please contact vl @ samba . org
2001-10-19 04:56:03 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-01-05 02:37:24 +03:00
void reply_writebs ( struct smb_request * req )
2001-10-19 04:56:03 +04:00
{
START_PROFILE ( SMBwriteBs ) ;
2009-12-21 22:16:38 +03:00
reply_force_doserror ( req , ERRSRV , ERRuseSTD ) ;
2001-10-19 04:56:03 +04:00
END_PROFILE ( SMBwriteBs ) ;
2007-08-15 13:52:09 +04:00
return ;
2001-10-19 04:56:03 +04:00
}
1996-05-04 11:50:46 +04:00
/****************************************************************************
2001-10-19 04:56:03 +04:00
Reply to a SMBgetattrE .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
2008-01-05 02:37:24 +03:00
void reply_getattrE ( struct smb_request * req )
1996-05-04 11:50:46 +04:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
2002-03-20 03:46:53 +03:00
int mode ;
2007-08-15 00:55:24 +04:00
files_struct * fsp ;
2008-08-28 02:06:14 +04:00
struct timespec create_ts ;
2019-09-09 08:57:34 +03:00
NTSTATUS status ;
2007-08-15 00:55:24 +04:00
2002-03-20 03:46:53 +03:00
START_PROFILE ( SMBgetattrE ) ;
1996-05-04 11:50:46 +04:00
2007-08-15 00:55:24 +04:00
if ( req - > wct < 1 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBgetattrE ) ;
return ;
}
2008-11-02 14:20:47 +03:00
fsp = file_fsp ( req , SVAL ( req - > vwv + 0 , 0 ) ) ;
1996-05-04 11:50:46 +04:00
2002-03-20 03:46:53 +03:00
if ( ! fsp | | ( fsp - > conn ! = conn ) ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_INVALID_HANDLE ) ;
2002-03-20 03:46:53 +03:00
END_PROFILE ( SMBgetattrE ) ;
2007-08-15 00:55:24 +04:00
return ;
2002-03-20 03:46:53 +03:00
}
1996-05-04 11:50:46 +04:00
2002-03-20 03:46:53 +03:00
/* Do an fstat on this file */
2019-09-09 08:57:34 +03:00
status = vfs_stat_fsp ( fsp ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
reply_nterror ( req , status ) ;
2002-03-20 03:46:53 +03:00
END_PROFILE ( SMBgetattrE ) ;
2007-08-15 00:55:24 +04:00
return ;
2002-03-20 03:46:53 +03:00
}
2008-10-19 17:30:12 +04:00
2020-10-19 21:49:02 +03:00
mode = fdos_mode ( fsp ) ;
2008-10-19 17:30:12 +04:00
2002-03-20 03:46:53 +03:00
/*
* Convert the times into dos times . Set create
* date to be last modify date as UNIX doesn ' t save
* this .
*/
2022-04-05 05:53:20 +03:00
reply_smb1_outbuf ( req , 11 , 0 ) ;
2007-08-15 00:55:24 +04:00
2009-08-13 00:00:54 +04:00
create_ts = get_create_timespec ( conn , fsp , fsp - > fsp_name ) ;
2008-08-28 02:06:14 +04:00
srv_put_dos_date2 ( ( char * ) req - > outbuf , smb_vwv0 , create_ts . tv_sec ) ;
2009-05-14 17:34:42 +04:00
srv_put_dos_date2 ( ( char * ) req - > outbuf , smb_vwv2 ,
2009-11-17 01:55:21 +03:00
convert_timespec_to_time_t ( fsp - > fsp_name - > st . st_ex_atime ) ) ;
2005-03-10 04:30:14 +03:00
/* Should we check pending modtime here ? JRA */
2009-05-14 17:34:42 +04:00
srv_put_dos_date2 ( ( char * ) req - > outbuf , smb_vwv4 ,
2009-11-17 01:55:21 +03:00
convert_timespec_to_time_t ( fsp - > fsp_name - > st . st_ex_mtime ) ) ;
2002-03-20 03:46:53 +03:00
2011-04-29 05:57:02 +04:00
if ( mode & FILE_ATTRIBUTE_DIRECTORY ) {
2007-08-15 00:55:24 +04:00
SIVAL ( req - > outbuf , smb_vwv6 , 0 ) ;
SIVAL ( req - > outbuf , smb_vwv8 , 0 ) ;
2002-03-20 03:46:53 +03:00
} else {
2015-04-27 02:02:55 +03:00
uint32_t allocation_size = SMB_VFS_GET_ALLOC_SIZE ( conn , fsp , & fsp - > fsp_name - > st ) ;
2015-05-03 07:01:14 +03:00
SIVAL ( req - > outbuf , smb_vwv6 , ( uint32_t ) fsp - > fsp_name - > st . st_ex_size ) ;
2007-08-15 00:55:24 +04:00
SIVAL ( req - > outbuf , smb_vwv8 , allocation_size ) ;
2002-03-20 03:46:53 +03:00
}
2007-08-15 00:55:24 +04:00
SSVAL ( req - > outbuf , smb_vwv10 , mode ) ;
2008-10-19 17:30:12 +04:00
2012-06-14 15:10:33 +04:00
DEBUG ( 3 , ( " reply_getattrE %s \n " , fsp_fnum_dbg ( fsp ) ) ) ;
2008-10-19 17:30:12 +04:00
2002-03-20 03:46:53 +03:00
END_PROFILE ( SMBgetattrE ) ;
2007-08-15 00:55:24 +04:00
return ;
1996-05-04 11:50:46 +04:00
}
2022-04-05 05:48:25 +03:00
/****************************************************************************
Reply to a SMBfindclose ( stop trans2 directory search ) .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void reply_findclose ( struct smb_request * req )
{
int dptr_num ;
struct smbd_server_connection * sconn = req - > sconn ;
files_struct * fsp = NULL ;
START_PROFILE ( SMBfindclose ) ;
if ( req - > wct < 1 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBfindclose ) ;
return ;
}
dptr_num = SVALS ( req - > vwv + 0 , 0 ) ;
DEBUG ( 3 , ( " reply_findclose, dptr_num = %d \n " , dptr_num ) ) ;
/*
* OS / 2 seems to use - 1 to indicate " close all directories "
* This has to mean on this specific connection struct .
*/
if ( dptr_num = = - 1 ) {
dptr_closecnum ( req - > conn ) ;
} else {
fsp = dptr_fetch_lanman2_fsp ( sconn , dptr_num ) ;
dptr_num = - 1 ;
if ( fsp ! = NULL ) {
close_file_free ( NULL , & fsp , NORMAL_CLOSE ) ;
}
}
2022-04-05 05:53:20 +03:00
reply_smb1_outbuf ( req , 0 , 0 ) ;
2022-04-05 05:48:25 +03:00
DEBUG ( 3 , ( " SMBfindclose dptr_num = %d \n " , dptr_num ) ) ;
END_PROFILE ( SMBfindclose ) ;
return ;
}
2022-04-05 05:50:58 +03:00
/****************************************************************************
Reply to a SMBfindnclose ( stop FINDNOTIFYFIRST directory search ) .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void reply_findnclose ( struct smb_request * req )
{
int dptr_num ;
START_PROFILE ( SMBfindnclose ) ;
if ( req - > wct < 1 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBfindnclose ) ;
return ;
}
dptr_num = SVAL ( req - > vwv + 0 , 0 ) ;
DEBUG ( 3 , ( " reply_findnclose, dptr_num = %d \n " , dptr_num ) ) ;
/* We never give out valid handles for a
findnotifyfirst - so any dptr_num is ok here .
Just ignore it . */
2022-04-05 05:53:20 +03:00
reply_smb1_outbuf ( req , 0 , 0 ) ;
2022-04-05 05:50:58 +03:00
DEBUG ( 3 , ( " SMB_findnclose dptr_num = %d \n " , dptr_num ) ) ;
END_PROFILE ( SMBfindnclose ) ;
return ;
}