2019-07-10 17:03:17 +03:00
/*
* Samba Unix / Linux SMB client library
* Distributed SMB / CIFS Server Management Utility
* Copyright ( C ) 2019 Ralph Boehme < slow @ samba . org >
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 3 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program . If not , see < http : //www.gnu.org/licenses/>.
*/
# include "includes.h"
# include <talloc.h>
# include <tevent.h>
# include <ftw.h>
# include "system/filesys.h"
# include "system/passwd.h"
# include "lib/param/loadparm.h"
# include "lib/param/param.h"
# include "libcli/security/security.h"
# include "smbd/proto.h"
2020-10-28 14:09:39 +03:00
# include "locking/share_mode_lock.h"
2019-07-10 17:03:17 +03:00
# include "locking/proto.h"
# include "auth.h"
2019-07-11 17:23:53 +03:00
# include "client.h"
# include "util_sd.h"
2019-07-10 17:03:17 +03:00
# include "lib/adouble.h"
# include "lib/string_replace.h"
# include "utils/net.h"
2021-01-03 23:53:49 +03:00
# include "lib/global_contexts.h"
2019-07-10 17:03:17 +03:00
# define NET_VFS_CMD_STREAM_TO_ADOUBLE "stream2adouble"
static struct net_vfs_state {
TALLOC_CTX * mem_ctx ;
struct net_context * c ;
struct auth_session_info * session_info ;
struct conn_struct_tos * conn_tos ;
} state ;
static void net_vfs_usage ( void )
{
fprintf ( stderr ,
" Usage: \n "
" net vfs [OPTIONS] <share> .... \n " ) ;
}
2019-07-11 17:23:53 +03:00
static void net_vfs_getntacl_usage ( void )
{
fprintf ( stderr ,
" Usage: \n "
" net vfs getntacl <share> <path> \n " ) ;
}
2019-07-10 17:03:17 +03:00
static void net_vfs_stream_to_appledouble_usage ( void )
{
fprintf ( stderr ,
" Usage: \n "
" net vfs " NET_VFS_CMD_STREAM_TO_ADOUBLE
" [OPTIONS] <share> <path> [<path> ...] \n "
" Options: \n "
" --verbose verbose output \n "
" --continue continue on error \n "
" --recursive traverse directory hierarchy \n "
" --follow-symlinks follow symlinks \n " ) ;
}
static bool net_vfs_make_session_info ( struct auth_session_info * * session_info )
{
NTSTATUS status ;
if ( non_root_mode ( ) ) {
struct passwd * p = NULL ;
p = getpwuid ( geteuid ( ) ) ;
if ( p = = NULL ) {
fprintf ( stderr , " getpwuid(%d) failed \n " , geteuid ( ) ) ;
return false ;
}
status = make_session_info_from_username ( state . mem_ctx ,
p - > pw_name ,
false ,
session_info ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
fprintf ( stderr , " session_info from username failed \n " ) ;
return false ;
}
return true ;
}
status = init_system_session_info ( state . mem_ctx ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
fprintf ( stderr , " init_system_session_info failed \n " ) ;
return false ;
}
status = make_session_info_system ( state . mem_ctx , session_info ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
fprintf ( stderr , " make_session_info_system failed \n " ) ;
return false ;
}
return true ;
}
static int net_vfs_init ( struct net_context * c , int argc , const char * * argv )
{
2019-10-31 21:14:02 +03:00
const struct loadparm_substitution * lp_sub =
loadparm_s3_global_substitution ( ) ;
2019-07-10 17:03:17 +03:00
const char * service = NULL ;
char * share_root = NULL ;
int snum ;
NTSTATUS status ;
bool ok ;
int rc = 1 ;
state = ( struct net_vfs_state ) {
. c = c ,
. mem_ctx = c ,
} ;
if ( argc < 1 ) {
net_vfs_usage ( ) ;
goto done ;
}
if ( geteuid ( ) ! = 0 & & ! uid_wrapper_enabled ( ) ) {
fprintf ( stderr , " 'net vfs' must be run as root. \n " ) ;
goto done ;
}
smb_init_locale ( ) ;
umask ( 0 ) ;
sec_init ( ) ;
setup_logging ( " net " , DEBUG_STDOUT ) ;
2023-08-07 06:56:07 +03:00
lpcfg_set_cmdline ( c - > lp_ctx , " log level " , " 0 " ) ;
2019-07-10 17:03:17 +03:00
2019-08-19 14:18:23 +03:00
ok = lp_load_with_registry_shares ( get_dyn_CONFIGFILE ( ) ) ;
2019-07-10 17:03:17 +03:00
if ( ! ok ) {
2019-08-19 14:18:23 +03:00
fprintf ( stderr , " lp_load_with_registry_shares failed \n " ) ;
2019-07-10 17:03:17 +03:00
goto done ;
}
ok = locking_init ( ) ;
if ( ! ok ) {
fprintf ( stderr , " locking init failed \n " ) ;
goto done ;
}
ok = net_vfs_make_session_info ( & state . session_info ) ;
if ( ! ok ) {
goto done ;
}
service = argv [ 0 ] ;
snum = lp_servicenumber ( service ) ;
if ( snum = = - 1 ) {
fprintf ( stderr , " unknown service: %s \n " , service ) ;
goto done ;
}
2019-10-31 21:14:02 +03:00
share_root = lp_path ( state . mem_ctx , lp_sub , snum ) ;
2019-07-10 17:03:17 +03:00
if ( share_root = = NULL ) {
fprintf ( stderr , " Failed to find share root for service: %s \n " ,
service ) ;
goto done ;
}
status = create_conn_struct_tos_cwd ( global_messaging_context ( ) ,
snum ,
share_root ,
state . session_info ,
& state . conn_tos ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto done ;
}
state . conn_tos - > conn - > share_access = FILE_GENERIC_ALL ;
state . conn_tos - > conn - > read_only = false ;
file_init ( state . conn_tos - > conn - > sconn ) ;
2019-07-19 12:14:13 +03:00
ok = become_user_without_service_by_session ( state . conn_tos - > conn ,
state . session_info ) ;
2019-07-10 17:03:17 +03:00
if ( ! ok ) {
2019-07-19 12:14:13 +03:00
fprintf ( stderr ,
" become_user_without_service_by_session failed \n " ) ;
2019-07-10 17:03:17 +03:00
goto done ;
}
rc = 0 ;
done :
return rc ;
}
2019-07-11 17:23:53 +03:00
static int net_vfs_get_ntacl ( struct net_context * net ,
int argc ,
const char * * argv )
{
const char * path = NULL ;
struct smb_filename * smb_fname = NULL ;
files_struct * fsp = NULL ;
struct security_descriptor * sd = NULL ;
NTSTATUS status ;
int ret ;
int rc = 1 ;
if ( argc < 2 | | net - > display_usage ) {
net_vfs_getntacl_usage ( ) ;
goto done ;
}
ret = net_vfs_init ( net , argc , argv ) ;
if ( ret ! = 0 ) {
goto done ;
}
path = argv [ 1 ] ;
2020-05-03 16:09:15 +03:00
smb_fname = synthetic_smb_fname ( state . mem_ctx ,
path ,
NULL ,
NULL ,
2020-04-30 12:48:32 +03:00
0 ,
2020-05-03 16:09:15 +03:00
0 ) ;
2019-07-11 17:23:53 +03:00
if ( smb_fname = = NULL ) {
goto done ;
}
ret = SMB_VFS_STAT ( state . conn_tos - > conn , smb_fname ) ;
if ( ret ! = 0 ) {
fprintf ( stderr , " stat [%s] failed: %s \n " ,
smb_fname_str_dbg ( smb_fname ) , strerror ( errno ) ) ;
goto done ;
}
2020-11-12 18:54:28 +03:00
status = openat_pathref_fsp ( state . conn_tos - > conn - > cwd_fsp , smb_fname ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DBG_ERR ( " openat_pathref_fsp [%s] failed: %s \n " ,
smb_fname_str_dbg ( smb_fname ) , nt_errstr ( status ) ) ;
goto done ;
}
2019-07-11 17:23:53 +03:00
status = SMB_VFS_CREATE_FILE (
state . conn_tos - > conn ,
NULL , /* req */
2021-11-23 14:29:17 +03:00
NULL ,
2019-07-11 17:23:53 +03:00
smb_fname ,
FILE_READ_ATTRIBUTES | READ_CONTROL_ACCESS ,
FILE_SHARE_READ | FILE_SHARE_WRITE ,
FILE_OPEN ,
0 , /* create_options */
0 , /* file_attributes */
INTERNAL_OPEN_ONLY , /* oplock_request */
NULL , /* lease */
0 , /* allocation_size */
0 , /* private_flags */
NULL , /* sd */
NULL , /* ea_list */
& fsp ,
NULL , /* info */
NULL , NULL ) ; /* create context */
if ( ! NT_STATUS_IS_OK ( status ) ) {
DBG_ERR ( " SMB_VFS_CREATE_FILE [%s] failed: %s \n " ,
smb_fname_str_dbg ( smb_fname ) , nt_errstr ( status ) ) ;
goto done ;
}
status = SMB_VFS_FGET_NT_ACL ( fsp ,
SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL ,
2023-01-12 14:00:26 +03:00
talloc_tos ( ) ,
2019-07-11 17:23:53 +03:00
& sd ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DBG_ERR ( " SMB_VFS_FGET_NT_ACL [%s] failed: %s \n " ,
smb_fname_str_dbg ( smb_fname ) , nt_errstr ( status ) ) ;
goto done ;
}
2022-02-01 19:47:29 +03:00
status = close_file_free ( NULL , & fsp , NORMAL_CLOSE ) ;
2019-07-11 17:23:53 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DBG_ERR ( " close_file [%s] failed: %s \n " ,
smb_fname_str_dbg ( smb_fname ) ,
nt_errstr ( status ) ) ;
goto done ;
}
sec_desc_print ( NULL , stdout , sd , true ) ;
rc = 0 ;
done :
2023-01-12 14:00:26 +03:00
TALLOC_FREE ( sd ) ;
2019-07-11 17:23:53 +03:00
if ( fsp ! = NULL ) {
2022-02-01 19:47:29 +03:00
status = close_file_free ( NULL , & fsp , NORMAL_CLOSE ) ;
2019-07-11 17:23:53 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2022-02-01 19:47:29 +03:00
DBG_ERR ( " close_file_free() [%s] failed: %s \n " ,
2019-07-11 17:23:53 +03:00
smb_fname_str_dbg ( smb_fname ) ,
nt_errstr ( status ) ) ;
rc = 1 ;
}
}
return rc ;
}
2019-07-10 17:03:17 +03:00
static bool do_unfruit ( const char * path )
{
struct smb_filename * smb_fname = NULL ;
char * p = NULL ;
bool converted ;
int ret ;
bool ok ;
p = strrchr_m ( path , ' / ' ) ;
if ( p ! = NULL ) {
if ( p [ 1 ] = = ' . ' & & p [ 2 ] = = ' _ ' ) {
return true ;
}
}
smb_fname = synthetic_smb_fname ( state . mem_ctx ,
path ,
NULL ,
NULL ,
2020-04-30 12:48:32 +03:00
0 ,
2019-07-10 17:03:17 +03:00
0 ) ;
if ( smb_fname = = NULL ) {
return false ;
}
ret = SMB_VFS_STAT ( state . conn_tos - > conn , smb_fname ) ;
if ( ret ! = 0 ) {
fprintf ( stderr , " %s: %s \n " , path , strerror ( errno ) ) ;
if ( state . c - > opt_continue_on_error ) {
return true ;
}
return false ;
}
ok = ad_unconvert ( state . mem_ctx ,
state . conn_tos - > conn - > vfs_handles ,
macos_string_replace_map ,
smb_fname ,
& converted ) ;
if ( ! ok ) {
fprintf ( stderr , " Converting failed: %s \n " , path ) ;
if ( state . c - > opt_continue_on_error ) {
return true ;
}
return false ;
}
if ( converted ) {
fprintf ( stdout , " Converted: %s \n " , path ) ;
} else if ( state . c - > opt_verbose ) {
fprintf ( stdout , " %s \n " , path ) ;
}
return true ;
}
static int nftw_cb ( const char * path ,
const struct stat * sb ,
int typeflag ,
struct FTW * ftwbuf )
{
bool ok ;
if ( typeflag = = FTW_SL ) {
if ( state . c - > opt_verbose ) {
fprintf ( stdout , " Ignoring symlink: %s \n " , path ) ;
}
return 0 ;
}
ok = do_unfruit ( path ) ;
if ( ! ok ) {
return - 1 ;
}
return 0 ;
}
static int net_vfs_stream_to_appledouble ( struct net_context * net ,
int argc ,
const char * * argv )
{
int i ;
int ret ;
bool ok ;
int rc = 1 ;
if ( argc < 2 | | net - > display_usage ) {
net_vfs_stream_to_appledouble_usage ( ) ;
goto done ;
}
ret = net_vfs_init ( net , argc , argv ) ;
if ( ret ! = 0 ) {
goto done ;
}
for ( i = 1 ; i < argc ; i + + ) {
const char * path = argv [ i ] ;
if ( path [ 0 ] = = ' / ' ) {
fprintf ( stderr , " ignoring absolute path: %s \n " , path ) ;
if ( state . c - > opt_continue_on_error ) {
continue ;
}
goto done ;
}
if ( ! state . c - > opt_recursive ) {
ok = do_unfruit ( path ) ;
if ( ! ok ) {
if ( ! state . c - > opt_continue_on_error ) {
goto done ;
}
}
continue ;
}
ret = nftw ( path ,
nftw_cb ,
256 ,
state . c - > opt_follow_symlink ? 0 : FTW_PHYS ) ;
if ( ret ! = 0 ) {
fprintf ( stderr , " %s: %s \n " , path , strerror ( errno ) ) ;
if ( ! state . c - > opt_continue_on_error ) {
goto done ;
}
}
}
rc = 0 ;
done :
return rc ;
}
static struct functable func [ ] = {
2019-07-11 17:23:53 +03:00
{
" getntacl " ,
net_vfs_get_ntacl ,
NET_TRANSPORT_LOCAL ,
N_ ( " Display security descriptor of a file or directory " ) ,
N_ ( " net vfs getntacl <share> <path> [<path> ...] " )
} ,
2019-07-10 17:03:17 +03:00
{
NET_VFS_CMD_STREAM_TO_ADOUBLE ,
net_vfs_stream_to_appledouble ,
NET_TRANSPORT_LOCAL ,
N_ ( " Convert streams to AppleDouble files " ) ,
N_ ( " net vfs " NET_VFS_CMD_STREAM_TO_ADOUBLE " [OPTIONS] <share> <path> [<path> ...] " )
} ,
{ NULL , NULL , 0 , NULL , NULL }
} ;
int net_vfs ( struct net_context * c , int argc , const char * * argv )
{
return net_run_function ( c , argc , argv , " net vfs " , func ) ;
}