2010-04-27 23:06:11 +04:00
/*
* Unix SMB / CIFS implementation .
* Group Policy Object Support
* Copyright ( C ) Wilco Baan Hofman 2008 - 2010
*
* 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"
2023-04-27 18:37:29 +03:00
# include "system/dir.h"
2011-10-08 14:10:20 +04:00
# include "system/filesys.h"
2010-04-27 23:06:11 +04:00
# include "lib/policy/policy.h"
# include "libcli/raw/smb.h"
# include "libcli/libcli.h"
# include "param/param.h"
# include "libcli/resolve/resolve.h"
2010-05-19 19:22:48 +04:00
# include "libcli/raw/libcliraw.h"
2010-05-06 20:42:14 +04:00
# include <dirent.h>
2010-05-25 03:21:45 +04:00
# include <errno.h>
2010-04-27 23:06:11 +04:00
# define GP_MAX_DEPTH 25
2010-05-25 03:21:45 +04:00
struct gp_file_entry {
bool is_directory ;
const char * rel_path ;
} ;
struct gp_file_list {
uint32_t num_files ;
struct gp_file_entry * files ;
} ;
2010-04-27 23:06:11 +04:00
struct gp_list_state {
2010-05-25 03:21:45 +04:00
struct smbcli_tree * tree ;
2010-04-27 23:06:11 +04:00
uint8_t depth ;
const char * cur_rel_path ;
const char * share_path ;
2010-05-25 03:21:45 +04:00
struct gp_file_list list ;
2010-04-27 23:06:11 +04:00
} ;
static NTSTATUS gp_do_list ( const char * , struct gp_list_state * ) ;
/* Create a temporary policy directory */
static const char * gp_tmpdir ( TALLOC_CTX * mem_ctx )
{
2010-05-25 03:21:45 +04:00
char * gp_dir = talloc_asprintf ( mem_ctx , " %s/policy " , tmpdir ( ) ) ;
2010-04-27 23:06:11 +04:00
struct stat st ;
2010-05-25 03:21:45 +04:00
int rv ;
2010-04-27 23:06:11 +04:00
2010-05-24 23:36:49 +04:00
if ( gp_dir = = NULL ) return NULL ;
2010-04-27 23:06:11 +04:00
if ( stat ( gp_dir , & st ) ! = 0 ) {
2010-05-25 03:21:45 +04:00
rv = mkdir ( gp_dir , 0755 ) ;
if ( rv < 0 ) {
DEBUG ( 0 , ( " Failed to create directory %s: %s \n " ,
gp_dir , strerror ( errno ) ) ) ;
talloc_free ( gp_dir ) ;
return NULL ;
}
2010-04-27 23:06:11 +04:00
}
return gp_dir ;
}
/* This function is called by the smbcli_list function */
2010-05-25 03:21:45 +04:00
static void gp_list_helper ( struct clilist_file_info * info , const char * mask ,
void * list_state_ptr )
2010-04-27 23:06:11 +04:00
{
struct gp_list_state * state = list_state_ptr ;
2010-05-25 03:21:45 +04:00
const char * rel_path ;
2010-04-27 23:06:11 +04:00
2010-05-25 03:21:45 +04:00
/* Ignore . and .. directory entries */
if ( strcmp ( info - > name , " . " ) = = 0 | | strcmp ( info - > name , " .. " ) = = 0 ) {
return ;
2010-04-27 23:06:11 +04:00
}
2010-05-25 03:21:45 +04:00
/* Safety check against ../.. in filenames which may occur on non-POSIX
* platforms */
if ( strstr ( info - > name , " ../ " ) ) {
return ;
}
2010-04-27 23:06:11 +04:00
2010-05-25 03:21:45 +04:00
rel_path = talloc_asprintf ( state , " %s \\ %s " , state - > cur_rel_path , info - > name ) ;
if ( rel_path = = NULL ) return ;
2010-04-27 23:06:11 +04:00
2010-05-25 03:21:45 +04:00
/* Append entry to file list */
state - > list . files = talloc_realloc ( state , state - > list . files ,
struct gp_file_entry ,
state - > list . num_files + 1 ) ;
if ( state - > list . files = = NULL ) return ;
2010-04-27 23:06:11 +04:00
2010-05-25 03:21:45 +04:00
state - > list . files [ state - > list . num_files ] . rel_path = rel_path ;
2010-04-27 23:06:11 +04:00
2010-05-25 03:21:45 +04:00
/* Directory */
if ( info - > attrib & FILE_ATTRIBUTE_DIRECTORY ) {
state - > list . files [ state - > list . num_files ] . is_directory = true ;
state - > list . num_files + + ;
2010-04-27 23:06:11 +04:00
2010-05-25 03:21:45 +04:00
/* Recurse into this directory if the depth is below the maximum */
if ( state - > depth < GP_MAX_DEPTH ) {
gp_do_list ( rel_path , state ) ;
}
2010-04-27 23:06:11 +04:00
return ;
}
2010-05-25 03:21:45 +04:00
state - > list . files [ state - > list . num_files ] . is_directory = false ;
state - > list . num_files + + ;
2010-04-27 23:06:11 +04:00
return ;
}
static NTSTATUS gp_do_list ( const char * rel_path , struct gp_list_state * state )
{
uint16_t attributes ;
2010-05-25 03:21:45 +04:00
int rv ;
2010-04-27 23:06:11 +04:00
char * mask ;
const char * old_rel_path ;
2010-05-25 03:21:45 +04:00
attributes = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN |
FILE_ATTRIBUTE_DIRECTORY ;
2010-04-27 23:06:11 +04:00
/* Update the relative paths, while buffering the parent */
old_rel_path = state - > cur_rel_path ;
state - > cur_rel_path = rel_path ;
state - > depth + + ;
/* Get the current mask */
2010-04-28 13:27:43 +04:00
mask = talloc_asprintf ( state , " %s%s \\ * " , state - > share_path , rel_path ) ;
2010-05-24 23:36:49 +04:00
NT_STATUS_HAVE_NO_MEMORY ( mask ) ;
2010-05-25 03:21:45 +04:00
rv = smbcli_list ( state - > tree , mask , attributes , gp_list_helper , state ) ;
2010-04-27 23:06:11 +04:00
talloc_free ( mask ) ;
/* Go back to the state of the parent */
state - > cur_rel_path = old_rel_path ;
state - > depth - - ;
2010-05-25 03:21:45 +04:00
if ( rv = = - 1 )
2010-04-27 23:06:11 +04:00
return NT_STATUS_UNSUCCESSFUL ;
return NT_STATUS_OK ;
}
static NTSTATUS gp_cli_connect ( struct gp_context * gp_ctx )
{
struct smbcli_options options ;
struct smbcli_session_options session_options ;
if ( gp_ctx - > cli ! = NULL )
return NT_STATUS_OK ;
gp_ctx - > cli = smbcli_state_init ( gp_ctx ) ;
2010-07-16 08:32:42 +04:00
lpcfg_smbcli_options ( gp_ctx - > lp_ctx , & options ) ;
lpcfg_smbcli_session_options ( gp_ctx - > lp_ctx , & session_options ) ;
2010-04-27 23:06:11 +04:00
return smbcli_full_connection ( gp_ctx ,
& gp_ctx - > cli ,
2011-08-21 04:24:12 +04:00
gp_ctx - > active_dc - > name ,
2010-07-16 08:32:42 +04:00
lpcfg_smb_ports ( gp_ctx - > lp_ctx ) ,
2010-04-27 23:06:11 +04:00
" sysvol " ,
NULL ,
2010-07-16 08:32:42 +04:00
lpcfg_socket_options ( gp_ctx - > lp_ctx ) ,
2010-04-27 23:06:11 +04:00
gp_ctx - > credentials ,
2010-07-16 08:32:42 +04:00
lpcfg_resolve_context ( gp_ctx - > lp_ctx ) ,
2010-04-27 23:06:11 +04:00
gp_ctx - > ev_ctx ,
& options ,
& session_options ,
2010-07-16 08:32:42 +04:00
lpcfg_gensec_settings ( gp_ctx , gp_ctx - > lp_ctx ) ) ;
2010-04-27 23:06:11 +04:00
}
2010-05-19 19:22:48 +04:00
static char * gp_get_share_path ( TALLOC_CTX * mem_ctx , const char * file_sys_path )
{
unsigned int i , bkslash_cnt ;
/* Get the path from the share down (\\..\..\(this\stuff) */
for ( i = 0 , bkslash_cnt = 0 ; file_sys_path [ i ] ! = ' \0 ' ; i + + ) {
if ( file_sys_path [ i ] = = ' \\ ' )
bkslash_cnt + + ;
if ( bkslash_cnt = = 4 ) {
return talloc_strdup ( mem_ctx , & file_sys_path [ i ] ) ;
}
}
return NULL ;
}
2010-05-25 03:21:45 +04:00
static NTSTATUS gp_get_file ( struct smbcli_tree * tree , const char * remote_src ,
const char * local_dst )
{
int fh_remote , fh_local ;
uint8_t * buf ;
size_t nread = 0 ;
size_t buf_size = 1024 ;
size_t file_size ;
uint16_t attr ;
/* Open the remote file */
fh_remote = smbcli_open ( tree , remote_src , O_RDONLY , DENY_NONE ) ;
if ( fh_remote = = - 1 ) {
DEBUG ( 0 , ( " Failed to open remote file: %s \n " , remote_src ) ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
/* Open the local file */
fh_local = open ( local_dst , O_WRONLY | O_CREAT | O_TRUNC , 0644 ) ;
if ( fh_local = = - 1 ) {
DEBUG ( 0 , ( " Failed to open local file: %s \n " , local_dst ) ) ;
2018-08-09 17:42:43 +03:00
smbcli_close ( tree , fh_remote ) ;
2010-05-25 03:21:45 +04:00
return NT_STATUS_UNSUCCESSFUL ;
}
/* Get the remote file size for error checking */
if ( NT_STATUS_IS_ERR ( smbcli_qfileinfo ( tree , fh_remote ,
& attr , & file_size , NULL , NULL , NULL , NULL , NULL ) ) & &
NT_STATUS_IS_ERR ( smbcli_getattrE ( tree , fh_remote ,
& attr , & file_size , NULL , NULL , NULL ) ) ) {
DEBUG ( 0 , ( " Failed to get remote file size: %s \n " , smbcli_errstr ( tree ) ) ) ;
2018-08-09 17:42:43 +03:00
smbcli_close ( tree , fh_remote ) ;
close ( fh_local ) ;
2010-05-25 03:21:45 +04:00
return NT_STATUS_UNSUCCESSFUL ;
}
buf = talloc_zero_array ( tree , uint8_t , buf_size ) ;
2018-08-09 17:42:43 +03:00
if ( buf = = NULL ) {
smbcli_close ( tree , fh_remote ) ;
close ( fh_local ) ;
return NT_STATUS_NO_MEMORY ;
}
2010-05-25 03:21:45 +04:00
/* Copy the contents of the file */
while ( 1 ) {
int n = smbcli_read ( tree , fh_remote , buf , nread , buf_size ) ;
if ( n < = 0 ) {
break ;
}
if ( write ( fh_local , buf , n ) ! = n ) {
DEBUG ( 0 , ( " Short write while copying file. \n " ) ) ;
2018-08-09 17:42:43 +03:00
smbcli_close ( tree , fh_remote ) ;
close ( fh_local ) ;
2010-05-25 03:21:45 +04:00
talloc_free ( buf ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
nread + = n ;
}
2018-08-09 17:42:43 +03:00
/* Close the files */
smbcli_close ( tree , fh_remote ) ;
close ( fh_local ) ;
talloc_free ( buf ) ;
2010-05-25 03:21:45 +04:00
/* Bytes read should match the file size, or the copy was incomplete */
if ( nread ! = file_size ) {
DEBUG ( 0 , ( " Remote/local file size mismatch after copying file: "
2010-06-20 22:34:48 +04:00
" %s (remote %zu, local %zu). \n " ,
2010-05-25 03:21:45 +04:00
remote_src , file_size , nread ) ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
return NT_STATUS_OK ;
}
static NTSTATUS gp_get_files ( struct smbcli_tree * tree , const char * share_path ,
const char * local_path , struct gp_file_list * list )
{
uint32_t i ;
int rv ;
char * local_rel_path , * full_local_path , * full_remote_path ;
TALLOC_CTX * mem_ctx ;
NTSTATUS status ;
mem_ctx = talloc_new ( tree ) ;
NT_STATUS_HAVE_NO_MEMORY ( mem_ctx ) ;
for ( i = 0 ; i < list - > num_files ; i + + ) {
/* Get local path by replacing backslashes with slashes */
local_rel_path = talloc_strdup ( mem_ctx , list - > files [ i ] . rel_path ) ;
2014-02-13 08:51:11 +04:00
if ( local_rel_path = = NULL ) {
TALLOC_FREE ( mem_ctx ) ;
return NT_STATUS_NO_MEMORY ;
}
2010-05-25 03:21:45 +04:00
string_replace ( local_rel_path , ' \\ ' , ' / ' ) ;
full_local_path = talloc_asprintf ( mem_ctx , " %s%s " , local_path ,
local_rel_path ) ;
2014-02-13 08:51:11 +04:00
if ( full_local_path = = NULL ) {
TALLOC_FREE ( mem_ctx ) ;
return NT_STATUS_NO_MEMORY ;
}
2010-05-25 03:21:45 +04:00
/* If the entry is a directory, create it. */
if ( list - > files [ i ] . is_directory = = true ) {
rv = mkdir ( full_local_path , 0755 ) ;
if ( rv < 0 ) {
DEBUG ( 0 , ( " Failed to create directory %s: %s \n " ,
full_local_path , strerror ( errno ) ) ) ;
talloc_free ( mem_ctx ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
continue ;
}
full_remote_path = talloc_asprintf ( mem_ctx , " %s%s " , share_path ,
list - > files [ i ] . rel_path ) ;
2014-02-13 08:51:11 +04:00
if ( full_remote_path = = NULL ) {
TALLOC_FREE ( mem_ctx ) ;
return NT_STATUS_NO_MEMORY ;
}
2010-05-25 03:21:45 +04:00
/* Get the file */
status = gp_get_file ( tree , full_remote_path , full_local_path ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " Error getting file. \n " ) ) ;
talloc_free ( mem_ctx ) ;
return status ;
}
}
return NT_STATUS_OK ;
}
2010-05-19 19:22:48 +04:00
2010-05-25 03:21:45 +04:00
NTSTATUS gp_fetch_gpt ( struct gp_context * gp_ctx , struct gp_object * gpo ,
const char * * ret_local_path )
2010-04-27 23:06:11 +04:00
{
TALLOC_CTX * mem_ctx ;
struct gp_list_state * state ;
NTSTATUS status ;
struct stat st ;
int rv ;
2010-05-25 03:21:45 +04:00
const char * local_path , * share_path ;
2010-04-27 23:06:11 +04:00
/* Create a forked memory context, as a base for everything here */
mem_ctx = talloc_new ( gp_ctx ) ;
2010-05-25 03:21:45 +04:00
NT_STATUS_HAVE_NO_MEMORY ( mem_ctx ) ;
2010-04-27 23:06:11 +04:00
if ( gp_ctx - > cli = = NULL ) {
status = gp_cli_connect ( gp_ctx ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " Failed to create cli connection to DC \n " ) ) ;
talloc_free ( mem_ctx ) ;
return status ;
}
}
2010-05-25 03:21:45 +04:00
/* Get the remote path to copy from */
share_path = gp_get_share_path ( mem_ctx , gpo - > file_sys_path ) ;
2014-02-13 08:51:11 +04:00
if ( share_path = = NULL ) {
TALLOC_FREE ( mem_ctx ) ;
return NT_STATUS_NO_MEMORY ;
}
2010-05-25 03:21:45 +04:00
/* Get the local path to copy to */
local_path = talloc_asprintf ( gp_ctx , " %s/%s " , gp_tmpdir ( mem_ctx ) , gpo - > name ) ;
2014-02-13 08:51:11 +04:00
if ( local_path = = NULL ) {
TALLOC_FREE ( mem_ctx ) ;
return NT_STATUS_NO_MEMORY ;
}
2010-05-25 03:21:45 +04:00
2010-04-27 23:06:11 +04:00
/* Prepare the state structure */
state = talloc_zero ( mem_ctx , struct gp_list_state ) ;
2014-02-13 08:51:11 +04:00
if ( state = = NULL ) {
TALLOC_FREE ( mem_ctx ) ;
return NT_STATUS_NO_MEMORY ;
}
2010-04-27 23:06:11 +04:00
2010-05-25 03:21:45 +04:00
state - > tree = gp_ctx - > cli - > tree ;
state - > share_path = share_path ;
2010-04-27 23:06:11 +04:00
/* Create the GPO dir if it does not exist */
2010-05-25 03:21:45 +04:00
if ( stat ( local_path , & st ) ! = 0 ) {
rv = mkdir ( local_path , 0755 ) ;
2010-04-27 23:06:11 +04:00
if ( rv < 0 ) {
DEBUG ( 0 , ( " Could not create local path \n " ) ) ;
talloc_free ( mem_ctx ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
}
2010-05-25 03:21:45 +04:00
/* Get the file list */
2010-04-27 23:06:11 +04:00
status = gp_do_list ( " " , state ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " Could not list GPO files on remote server \n " ) ) ;
talloc_free ( mem_ctx ) ;
return status ;
}
2010-05-25 03:21:45 +04:00
/* If the list has no entries there is a problem. */
if ( state - > list . num_files = = 0 ) {
DEBUG ( 0 , ( " File list is has no entries. Is the GPT directory empty? \n " ) ) ;
talloc_free ( mem_ctx ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
/* Fetch the files */
status = gp_get_files ( gp_ctx - > cli - > tree , share_path , local_path , & state - > list ) ;
2010-04-27 23:06:11 +04:00
/* Return the local path to the gpo */
2010-05-25 03:21:45 +04:00
* ret_local_path = local_path ;
2010-04-27 23:06:11 +04:00
talloc_free ( mem_ctx ) ;
return NT_STATUS_OK ;
}
2010-05-06 20:42:14 +04:00
2010-05-25 03:21:45 +04:00
static NTSTATUS push_recursive ( struct gp_context * gp_ctx , const char * local_path ,
const char * remote_path , int depth )
2010-05-06 20:42:14 +04:00
{
DIR * dir ;
struct dirent * dirent ;
2013-02-20 13:22:00 +04:00
char * entry_local_path = NULL ;
char * entry_remote_path = NULL ;
2019-12-09 11:58:42 +03:00
int local_fd = - 1 , remote_fd = - 1 ;
2023-04-27 18:37:29 +03:00
char buf [ 4096 ] ;
ssize_t nread , total_read ;
ssize_t nwrite , total_write ;
2010-06-20 22:23:56 +04:00
struct stat s ;
2013-02-20 13:22:00 +04:00
NTSTATUS status ;
2010-05-06 20:42:14 +04:00
dir = opendir ( local_path ) ;
2023-04-27 18:37:29 +03:00
if ( ! dir ) {
DEBUG ( 0 , ( " Failed to open directory: %s \n " , local_path ) ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
2010-05-06 20:42:14 +04:00
while ( ( dirent = readdir ( dir ) ) ! = NULL ) {
2023-04-27 18:37:29 +03:00
if ( ISDOT ( dirent - > d_name ) | | ISDOTDOT ( dirent - > d_name ) ) {
2010-05-06 20:42:14 +04:00
continue ;
}
2010-05-25 03:21:45 +04:00
entry_local_path = talloc_asprintf ( gp_ctx , " %s/%s " , local_path ,
dirent - > d_name ) ;
2013-02-20 13:22:00 +04:00
if ( entry_local_path = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto done ;
}
2010-05-25 03:21:45 +04:00
entry_remote_path = talloc_asprintf ( gp_ctx , " %s \\ %s " ,
remote_path , dirent - > d_name ) ;
2013-02-20 13:22:00 +04:00
if ( entry_remote_path = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto done ;
}
2010-05-25 03:21:45 +04:00
2011-08-02 09:13:36 +04:00
if ( stat ( entry_local_path , & s ) ! = 0 ) {
2013-02-20 13:22:00 +04:00
status = NT_STATUS_UNSUCCESSFUL ;
goto done ;
2010-06-20 22:23:56 +04:00
}
if ( s . st_mode & S_IFDIR ) {
2010-05-25 03:21:45 +04:00
DEBUG ( 6 , ( " Pushing directory %s to %s on sysvol \n " ,
entry_local_path , entry_remote_path ) ) ;
2023-04-27 18:37:29 +03:00
status = smbcli_mkdir ( gp_ctx - > cli - > tree ,
entry_remote_path ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto done ;
}
2010-05-25 03:21:45 +04:00
if ( depth < GP_MAX_DEPTH ) {
2023-04-27 18:37:29 +03:00
status = push_recursive ( gp_ctx ,
entry_local_path ,
entry_remote_path ,
depth + 1 ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto done ;
}
2010-05-25 03:21:45 +04:00
}
2010-05-06 20:42:14 +04:00
} else {
2010-05-25 03:21:45 +04:00
DEBUG ( 6 , ( " Pushing file %s to %s on sysvol \n " ,
entry_local_path , entry_remote_path ) ) ;
remote_fd = smbcli_open ( gp_ctx - > cli - > tree ,
entry_remote_path ,
O_WRONLY | O_CREAT ,
0 ) ;
2010-05-06 20:42:14 +04:00
if ( remote_fd < 0 ) {
2010-05-25 03:21:45 +04:00
DEBUG ( 0 , ( " Failed to create remote file: %s \n " ,
entry_remote_path ) ) ;
2013-02-20 13:22:00 +04:00
status = NT_STATUS_UNSUCCESSFUL ;
goto done ;
2010-05-06 20:42:14 +04:00
}
local_fd = open ( entry_local_path , O_RDONLY ) ;
if ( local_fd < 0 ) {
2010-05-25 03:21:45 +04:00
DEBUG ( 0 , ( " Failed to open local file: %s \n " ,
entry_local_path ) ) ;
2013-02-20 13:22:00 +04:00
status = NT_STATUS_UNSUCCESSFUL ;
goto done ;
2010-05-06 20:42:14 +04:00
}
total_read = 0 ;
2023-04-27 18:37:29 +03:00
total_write = 0 ;
while ( ( nread = read ( local_fd , buf , sizeof ( buf ) ) ) ) {
2019-05-08 07:46:33 +03:00
if ( nread = = - 1 ) {
DBG_ERR ( " read failed with errno %s \n " ,
strerror ( errno ) ) ;
status = NT_STATUS_UNSUCCESSFUL ;
goto done ;
}
2023-04-27 18:37:29 +03:00
nwrite = smbcli_write ( gp_ctx - > cli - > tree ,
remote_fd , 0 , buf ,
total_read , nread ) ;
if ( nwrite < 0 ) {
status = NT_STATUS_UNSUCCESSFUL ;
goto done ;
}
2010-05-06 20:42:14 +04:00
total_read + = nread ;
2023-04-27 18:37:29 +03:00
total_write + = nwrite ;
}
if ( total_read ! = total_write ) {
/* Weird and should not happen */
status = NT_STATUS_UNEXPECTED_IO_ERROR ;
goto done ;
2010-05-06 20:42:14 +04:00
}
close ( local_fd ) ;
2019-12-09 11:58:42 +03:00
local_fd = - 1 ;
2010-05-06 20:42:14 +04:00
smbcli_close ( gp_ctx - > cli - > tree , remote_fd ) ;
2019-12-09 11:58:42 +03:00
remote_fd = - 1 ;
2010-05-06 20:42:14 +04:00
}
2013-02-20 13:22:00 +04:00
TALLOC_FREE ( entry_local_path ) ;
TALLOC_FREE ( entry_remote_path ) ;
2010-05-06 20:42:14 +04:00
}
2013-02-20 13:22:00 +04:00
status = NT_STATUS_OK ;
done :
2019-12-09 11:58:42 +03:00
if ( local_fd ! = - 1 ) {
close ( local_fd ) ;
}
if ( remote_fd ! = - 1 ) {
smbcli_close ( gp_ctx - > cli - > tree , remote_fd ) ;
}
2013-02-20 13:22:00 +04:00
talloc_free ( entry_local_path ) ;
talloc_free ( entry_remote_path ) ;
2010-05-06 20:42:14 +04:00
closedir ( dir ) ;
2013-02-20 13:22:00 +04:00
return status ;
2010-05-06 20:42:14 +04:00
}
2010-05-25 03:21:45 +04:00
NTSTATUS gp_push_gpt ( struct gp_context * gp_ctx , const char * local_path ,
const char * file_sys_path )
2010-05-06 20:42:14 +04:00
{
NTSTATUS status ;
char * share_path ;
if ( gp_ctx - > cli = = NULL ) {
status = gp_cli_connect ( gp_ctx ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " Failed to create cli connection to DC \n " ) ) ;
return status ;
}
}
2010-05-19 19:22:48 +04:00
share_path = gp_get_share_path ( gp_ctx , file_sys_path ) ;
2010-05-06 20:42:14 +04:00
DEBUG ( 5 , ( " Copying %s to %s on sysvol \n " , local_path , share_path ) ) ;
smbcli_mkdir ( gp_ctx - > cli - > tree , share_path ) ;
status = push_recursive ( gp_ctx , local_path , share_path , 0 ) ;
talloc_free ( share_path ) ;
return status ;
}
2010-05-25 03:21:45 +04:00
NTSTATUS gp_create_gpt ( struct gp_context * gp_ctx , const char * name ,
const char * file_sys_path )
2010-05-06 20:42:14 +04:00
{
TALLOC_CTX * mem_ctx ;
const char * tmp_dir , * policy_dir , * tmp_str ;
int rv ;
int fd ;
NTSTATUS status ;
2010-05-24 21:53:12 +04:00
const char * file_content = " [General] \r \n Version=0 \r \n " ;
2010-05-06 20:42:14 +04:00
/* Create a forked memory context, as a base for everything here */
mem_ctx = talloc_new ( gp_ctx ) ;
2010-05-24 23:36:49 +04:00
NT_STATUS_HAVE_NO_MEMORY ( mem_ctx ) ;
2010-05-06 20:42:14 +04:00
tmp_dir = gp_tmpdir ( mem_ctx ) ;
2010-05-24 23:36:49 +04:00
NT_STATUS_HAVE_NO_MEMORY ( tmp_dir ) ;
2010-05-06 20:42:14 +04:00
policy_dir = talloc_asprintf ( mem_ctx , " %s/%s " , tmp_dir , name ) ;
2010-05-24 23:36:49 +04:00
NT_STATUS_HAVE_NO_MEMORY ( policy_dir ) ;
2010-05-19 19:22:48 +04:00
/* Create the directories */
2010-05-06 20:42:14 +04:00
rv = mkdir ( policy_dir , 0755 ) ;
if ( rv < 0 ) {
DEBUG ( 0 , ( " Could not create the policy dir: %s \n " , policy_dir ) ) ;
talloc_free ( mem_ctx ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
tmp_str = talloc_asprintf ( mem_ctx , " %s/User " , policy_dir ) ;
2010-05-24 23:36:49 +04:00
NT_STATUS_HAVE_NO_MEMORY ( tmp_str ) ;
2010-05-06 20:42:14 +04:00
rv = mkdir ( tmp_str , 0755 ) ;
if ( rv < 0 ) {
DEBUG ( 0 , ( " Could not create the User dir: %s \n " , tmp_str ) ) ;
talloc_free ( mem_ctx ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
tmp_str = talloc_asprintf ( mem_ctx , " %s/Machine " , policy_dir ) ;
2010-05-24 23:36:49 +04:00
NT_STATUS_HAVE_NO_MEMORY ( tmp_str ) ;
2010-05-06 20:42:14 +04:00
rv = mkdir ( tmp_str , 0755 ) ;
if ( rv < 0 ) {
DEBUG ( 0 , ( " Could not create the Machine dir: %s \n " , tmp_str ) ) ;
talloc_free ( mem_ctx ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
2010-05-19 19:22:48 +04:00
/* Create a GPT.INI with version 0 */
2010-05-06 20:42:14 +04:00
tmp_str = talloc_asprintf ( mem_ctx , " %s/GPT.INI " , policy_dir ) ;
2010-05-24 23:36:49 +04:00
NT_STATUS_HAVE_NO_MEMORY ( tmp_str ) ;
2010-05-06 20:42:14 +04:00
fd = open ( tmp_str , O_CREAT | O_WRONLY , 0644 ) ;
if ( fd < 0 ) {
DEBUG ( 0 , ( " Could not create the GPT.INI: %s \n " , tmp_str ) ) ;
talloc_free ( mem_ctx ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
2010-05-24 21:53:12 +04:00
rv = write ( fd , file_content , strlen ( file_content ) ) ;
2013-11-10 22:45:11 +04:00
close ( fd ) ;
2010-05-24 21:53:12 +04:00
if ( rv ! = strlen ( file_content ) ) {
2010-05-06 20:42:14 +04:00
DEBUG ( 0 , ( " Short write in GPT.INI \n " ) ) ;
talloc_free ( mem_ctx ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
2010-05-19 19:22:48 +04:00
/* Upload the GPT to the sysvol share on a DC */
2010-05-06 20:42:14 +04:00
status = gp_push_gpt ( gp_ctx , policy_dir , file_sys_path ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
talloc_free ( mem_ctx ) ;
return status ;
}
talloc_free ( mem_ctx ) ;
return NT_STATUS_OK ;
}
2010-05-19 19:22:48 +04:00
2010-05-25 03:21:45 +04:00
NTSTATUS gp_set_gpt_security_descriptor ( struct gp_context * gp_ctx ,
struct gp_object * gpo ,
struct security_descriptor * sd )
2010-05-19 19:22:48 +04:00
{
TALLOC_CTX * mem_ctx ;
NTSTATUS status ;
union smb_setfileinfo fileinfo ;
union smb_open io ;
union smb_close io_close ;
/* Create a connection to sysvol if it is not already there */
if ( gp_ctx - > cli = = NULL ) {
status = gp_cli_connect ( gp_ctx ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " Failed to create cli connection to DC \n " ) ) ;
return status ;
}
}
/* Create a forked memory context which can be freed easily */
mem_ctx = talloc_new ( gp_ctx ) ;
2010-05-24 23:36:49 +04:00
NT_STATUS_HAVE_NO_MEMORY ( mem_ctx ) ;
2010-05-19 19:22:48 +04:00
/* Open the directory with NTCreate AndX call */
io . generic . level = RAW_OPEN_NTCREATEX ;
io . ntcreatex . in . root_fid . fnum = 0 ;
io . ntcreatex . in . flags = 0 ;
io . ntcreatex . in . access_mask = SEC_FLAG_MAXIMUM_ALLOWED ;
io . ntcreatex . in . create_options = 0 ;
io . ntcreatex . in . file_attr = FILE_ATTRIBUTE_NORMAL ;
2010-05-25 03:21:45 +04:00
io . ntcreatex . in . share_access = NTCREATEX_SHARE_ACCESS_READ |
NTCREATEX_SHARE_ACCESS_WRITE ;
2010-05-19 19:22:48 +04:00
io . ntcreatex . in . alloc_size = 0 ;
io . ntcreatex . in . open_disposition = NTCREATEX_DISP_OPEN ;
io . ntcreatex . in . impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS ;
io . ntcreatex . in . security_flags = 0 ;
io . ntcreatex . in . fname = gp_get_share_path ( mem_ctx , gpo - > file_sys_path ) ;
status = smb_raw_open ( gp_ctx - > cli - > tree , mem_ctx , & io ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " Can't open GPT directory \n " ) ) ;
talloc_free ( mem_ctx ) ;
return status ;
}
/* Set the security descriptor on the directory */
2017-11-19 20:56:50 +03:00
fileinfo . generic . level = RAW_SFILEINFO_SEC_DESC ;
2010-05-19 19:22:48 +04:00
fileinfo . set_secdesc . in . file . fnum = io . ntcreatex . out . file . fnum ;
2010-05-25 03:21:45 +04:00
fileinfo . set_secdesc . in . secinfo_flags = SECINFO_PROTECTED_DACL |
SECINFO_OWNER |
SECINFO_GROUP |
SECINFO_DACL ;
2010-05-19 19:22:48 +04:00
fileinfo . set_secdesc . in . sd = sd ;
status = smb_raw_setfileinfo ( gp_ctx - > cli - > tree , & fileinfo ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " Failed to set security descriptor on the GPT \n " ) ) ;
talloc_free ( mem_ctx ) ;
return status ;
}
/* Close the directory */
io_close . close . level = RAW_CLOSE_CLOSE ;
io_close . close . in . file . fnum = io . ntcreatex . out . file . fnum ;
io_close . close . in . write_time = 0 ;
status = smb_raw_close ( gp_ctx - > cli - > tree , & io_close ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " Failed to close directory \n " ) ) ;
talloc_free ( mem_ctx ) ;
return status ;
}
talloc_free ( mem_ctx ) ;
return NT_STATUS_OK ;
}