2006-07-11 22:01:26 +04:00
/*
* Unix SMB / Netbios implementation .
* Utility for managing share permissions
*
* Copyright ( C ) Tim Potter 2000
* Copyright ( C ) Jeremy Allison 2000
* Copyright ( C ) Jelmer Vernooij 2003
* Copyright ( C ) Gerald ( Jerry ) Carter 2005.
*
* 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
2006-07-11 22:01:26 +04:00
* ( 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
2007-07-10 09:23:25 +04:00
* along with this program ; if not , see < http : //www.gnu.org/licenses/>.
2006-07-11 22:01:26 +04:00
*/
# include "includes.h"
2007-02-18 04:31:50 +03:00
static TALLOC_CTX * ctx ;
2006-07-11 22:01:26 +04:00
2008-12-25 04:03:22 +03:00
enum acl_mode { SMB_ACL_DELETE ,
SMB_ACL_MODIFY ,
SMB_ACL_ADD ,
SMB_ACL_SET ,
2008-12-29 04:22:28 +03:00
SMB_SD_DELETE ,
2008-12-25 04:03:22 +03:00
SMB_ACL_VIEW } ;
2006-07-11 22:01:26 +04:00
struct perm_value {
const char * perm ;
uint32 mask ;
} ;
/* These values discovered by inspection */
static const struct perm_value special_values [ ] = {
2007-02-18 04:31:50 +03:00
{ " R " , SEC_RIGHTS_FILE_READ } ,
{ " W " , SEC_RIGHTS_FILE_WRITE } ,
{ " X " , SEC_RIGHTS_FILE_EXECUTE } ,
{ " D " , SEC_STD_DELETE } ,
{ " P " , SEC_STD_WRITE_DAC } ,
{ " O " , SEC_STD_WRITE_OWNER } ,
2006-07-11 22:01:26 +04:00
{ NULL , 0 } ,
} ;
2008-12-25 04:03:22 +03:00
# define SEC_RIGHTS_DIR_CHANGE ( SEC_RIGHTS_DIR_READ|SEC_STD_DELETE|\
SEC_RIGHTS_DIR_WRITE | SEC_DIR_TRAVERSE )
2007-02-18 04:31:50 +03:00
2006-07-11 22:01:26 +04:00
static const struct perm_value standard_values [ ] = {
2007-02-18 04:31:50 +03:00
{ " READ " , SEC_RIGHTS_DIR_READ | SEC_DIR_TRAVERSE } ,
{ " CHANGE " , SEC_RIGHTS_DIR_CHANGE } ,
{ " FULL " , SEC_RIGHTS_DIR_ALL } ,
2006-07-11 22:01:26 +04:00
{ NULL , 0 } ,
} ;
/********************************************************************
2007-02-18 04:31:50 +03:00
print an ACE on a FILE
2006-07-11 22:01:26 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void print_ace ( FILE * f , SEC_ACE * ace )
{
const struct perm_value * v ;
int do_print = 0 ;
uint32 got_mask ;
2007-12-15 23:53:26 +03:00
fprintf ( f , " %s: " , sid_string_tos ( & ace - > trustee ) ) ;
2006-07-11 22:01:26 +04:00
/* Ace type */
if ( ace - > type = = SEC_ACE_TYPE_ACCESS_ALLOWED ) {
fprintf ( f , " ALLOWED " ) ;
} else if ( ace - > type = = SEC_ACE_TYPE_ACCESS_DENIED ) {
fprintf ( f , " DENIED " ) ;
} else {
fprintf ( f , " %d " , ace - > type ) ;
}
/* Not sure what flags can be set in a file ACL */
fprintf ( f , " /%d/ " , ace - > flags ) ;
/* Standard permissions */
for ( v = standard_values ; v - > perm ; v + + ) {
2006-09-21 02:23:12 +04:00
if ( ace - > access_mask = = v - > mask ) {
2006-07-11 22:01:26 +04:00
fprintf ( f , " %s " , v - > perm ) ;
return ;
}
}
/* Special permissions. Print out a hex value if we have
leftover bits in the mask . */
2006-09-21 02:23:12 +04:00
got_mask = ace - > access_mask ;
2006-07-11 22:01:26 +04:00
again :
for ( v = special_values ; v - > perm ; v + + ) {
2006-09-21 02:23:12 +04:00
if ( ( ace - > access_mask & v - > mask ) = = v - > mask ) {
2006-07-11 22:01:26 +04:00
if ( do_print ) {
fprintf ( f , " %s " , v - > perm ) ;
}
got_mask & = ~ v - > mask ;
}
}
if ( ! do_print ) {
if ( got_mask ! = 0 ) {
2006-09-21 02:23:12 +04:00
fprintf ( f , " 0x%08x " , ace - > access_mask ) ;
2006-07-11 22:01:26 +04:00
} else {
do_print = 1 ;
goto again ;
}
}
}
/********************************************************************
2008-12-25 04:03:22 +03:00
print an ascii version of a security descriptor on a FILE handle
2006-07-11 22:01:26 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void sec_desc_print ( FILE * f , SEC_DESC * sd )
{
uint32 i ;
fprintf ( f , " REVISION:%d \n " , sd - > revision ) ;
/* Print owner and group sid */
2007-12-15 23:53:26 +03:00
fprintf ( f , " OWNER:%s \n " , sid_string_tos ( sd - > owner_sid ) ) ;
2006-07-11 22:01:26 +04:00
2007-12-15 23:53:26 +03:00
fprintf ( f , " GROUP:%s \n " , sid_string_tos ( sd - > group_sid ) ) ;
2006-07-11 22:01:26 +04:00
/* Print aces */
for ( i = 0 ; sd - > dacl & & i < sd - > dacl - > num_aces ; i + + ) {
2006-09-21 02:23:12 +04:00
SEC_ACE * ace = & sd - > dacl - > aces [ i ] ;
2006-07-11 22:01:26 +04:00
fprintf ( f , " ACL: " ) ;
print_ace ( f , ace ) ;
fprintf ( f , " \n " ) ;
}
}
/********************************************************************
2008-12-25 04:03:22 +03:00
parse an ACE in the same format as print_ace ( )
2006-07-11 22:01:26 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-19 04:40:25 +04:00
static bool parse_ace ( SEC_ACE * ace , const char * orig_str )
2006-07-11 22:01:26 +04:00
{
2007-02-18 04:31:50 +03:00
char * p ;
const char * cp ;
2007-12-08 04:32:32 +03:00
char * tok ;
2007-02-18 04:31:50 +03:00
unsigned int atype = 0 ;
unsigned int aflags = 0 ;
unsigned int amask = 0 ;
2006-07-11 22:01:26 +04:00
DOM_SID sid ;
2008-10-09 20:49:03 +04:00
uint32_t mask ;
2007-02-18 04:31:50 +03:00
const struct perm_value * v ;
char * str = SMB_STRDUP ( orig_str ) ;
2007-12-08 04:32:32 +03:00
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2007-02-18 04:31:50 +03:00
if ( ! str ) {
2007-12-08 04:32:32 +03:00
TALLOC_FREE ( frame ) ;
2006-07-11 22:01:26 +04:00
return False ;
2007-02-18 04:31:50 +03:00
}
ZERO_STRUCTP ( ace ) ;
p = strchr_m ( str , ' : ' ) ;
if ( ! p ) {
2008-12-29 04:21:36 +03:00
fprintf ( stderr , " ACE '%s': missing ':'. \n " , orig_str ) ;
2007-02-18 04:31:50 +03:00
SAFE_FREE ( str ) ;
2007-12-08 04:32:32 +03:00
TALLOC_FREE ( frame ) ;
2007-02-18 04:31:50 +03:00
return False ;
}
2006-07-11 22:01:26 +04:00
* p = ' \0 ' ;
p + + ;
2007-02-18 04:31:50 +03:00
/* Try to parse numeric form */
2006-07-11 22:01:26 +04:00
2007-02-18 04:31:50 +03:00
if ( sscanf ( p , " %i/%i/%i " , & atype , & aflags , & amask ) = = 3 & &
string_to_sid ( & sid , str ) ) {
goto done ;
}
2006-07-11 22:01:26 +04:00
2007-02-18 04:31:50 +03:00
/* Try to parse text form */
if ( ! string_to_sid ( & sid , str ) ) {
2008-12-29 04:21:36 +03:00
fprintf ( stderr , " ACE '%s': failed to convert '%s' to SID \n " ,
2007-02-18 04:31:50 +03:00
orig_str , str ) ;
SAFE_FREE ( str ) ;
2007-12-08 04:32:32 +03:00
TALLOC_FREE ( frame ) ;
2007-02-18 04:31:50 +03:00
return False ;
}
cp = p ;
2007-12-08 04:32:32 +03:00
if ( ! next_token_talloc ( frame , & cp , & tok , " / " ) ) {
2008-12-29 04:21:36 +03:00
fprintf ( stderr , " ACE '%s': failed to find '/' character. \n " ,
2007-02-18 04:31:50 +03:00
orig_str ) ;
SAFE_FREE ( str ) ;
2007-12-08 04:32:32 +03:00
TALLOC_FREE ( frame ) ;
2007-02-18 04:31:50 +03:00
return False ;
}
if ( strncmp ( tok , " ALLOWED " , strlen ( " ALLOWED " ) ) = = 0 ) {
atype = SEC_ACE_TYPE_ACCESS_ALLOWED ;
} else if ( strncmp ( tok , " DENIED " , strlen ( " DENIED " ) ) = = 0 ) {
atype = SEC_ACE_TYPE_ACCESS_DENIED ;
} else {
2008-12-29 04:21:36 +03:00
fprintf ( stderr , " ACE '%s': missing 'ALLOWED' or 'DENIED' "
" entry at '%s' \n " , orig_str , tok ) ;
2007-02-18 04:31:50 +03:00
SAFE_FREE ( str ) ;
2007-12-08 04:32:32 +03:00
TALLOC_FREE ( frame ) ;
2007-02-18 04:31:50 +03:00
return False ;
2006-07-11 22:01:26 +04:00
}
2007-02-18 04:31:50 +03:00
/* Only numeric form accepted for flags at present */
2006-07-11 22:01:26 +04:00
/* no flags on share permissions */
2007-02-18 04:31:50 +03:00
2007-12-08 04:32:32 +03:00
if ( ! ( next_token_talloc ( frame , & cp , & tok , " / " ) & &
2007-02-18 04:31:50 +03:00
sscanf ( tok , " %i " , & aflags ) & & aflags = = 0 ) ) {
2008-12-29 04:21:36 +03:00
fprintf ( stderr , " ACE '%s': bad integer flags entry at '%s' \n " ,
2007-02-18 04:31:50 +03:00
orig_str , tok ) ;
SAFE_FREE ( str ) ;
2007-12-08 04:32:32 +03:00
TALLOC_FREE ( frame ) ;
2007-02-18 04:31:50 +03:00
return False ;
}
2007-12-08 04:32:32 +03:00
if ( ! next_token_talloc ( frame , & cp , & tok , " / " ) ) {
2008-12-29 04:21:36 +03:00
fprintf ( stderr , " ACE '%s': missing / at '%s' \n " ,
2007-02-18 04:31:50 +03:00
orig_str , tok ) ;
SAFE_FREE ( str ) ;
2007-12-08 04:32:32 +03:00
TALLOC_FREE ( frame ) ;
2007-02-18 04:31:50 +03:00
return False ;
}
if ( strncmp ( tok , " 0x " , 2 ) = = 0 ) {
if ( sscanf ( tok , " %i " , & amask ) ! = 1 ) {
2008-12-29 04:21:36 +03:00
fprintf ( stderr , " ACE '%s': bad hex number at '%s' \n " ,
2007-02-18 04:31:50 +03:00
orig_str , tok ) ;
2007-12-08 04:32:32 +03:00
TALLOC_FREE ( frame ) ;
2007-02-18 04:31:50 +03:00
SAFE_FREE ( str ) ;
return False ;
}
goto done ;
}
for ( v = standard_values ; v - > perm ; v + + ) {
if ( strcmp ( tok , v - > perm ) = = 0 ) {
amask = v - > mask ;
goto done ;
}
}
p = tok ;
while ( * p ) {
2007-10-19 04:40:25 +04:00
bool found = False ;
2007-02-18 04:31:50 +03:00
for ( v = special_values ; v - > perm ; v + + ) {
if ( v - > perm [ 0 ] = = * p ) {
amask | = v - > mask ;
found = True ;
}
}
if ( ! found ) {
2008-12-29 04:21:36 +03:00
fprintf ( stderr , " ACE '%s': bad permission value at "
" '%s' \n " , orig_str , p ) ;
2007-12-08 04:32:32 +03:00
TALLOC_FREE ( frame ) ;
2007-02-18 04:31:50 +03:00
SAFE_FREE ( str ) ;
2008-12-25 04:03:22 +03:00
return False ;
2007-02-18 04:31:50 +03:00
}
p + + ;
}
if ( * p ) {
2007-12-08 04:32:32 +03:00
TALLOC_FREE ( frame ) ;
2007-02-18 04:31:50 +03:00
SAFE_FREE ( str ) ;
return False ;
}
done :
mask = amask ;
init_sec_ace ( ace , & sid , atype , mask , aflags ) ;
SAFE_FREE ( str ) ;
2007-12-08 04:32:32 +03:00
TALLOC_FREE ( frame ) ;
2006-07-11 22:01:26 +04:00
return True ;
}
/********************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-02-18 04:31:50 +03:00
static SEC_DESC * parse_acl_string ( TALLOC_CTX * mem_ctx , const char * szACL , size_t * sd_size )
2006-07-11 22:01:26 +04:00
{
SEC_DESC * sd = NULL ;
SEC_ACE * ace ;
SEC_ACL * acl ;
int num_ace ;
const char * pacl ;
int i ;
2008-12-25 04:03:22 +03:00
2006-07-11 22:01:26 +04:00
if ( ! szACL )
return NULL ;
pacl = szACL ;
num_ace = count_chars ( pacl , ' , ' ) + 1 ;
2008-12-25 04:03:22 +03:00
if ( ! ( ace = TALLOC_ZERO_ARRAY ( mem_ctx , SEC_ACE , num_ace ) ) )
2006-07-11 22:01:26 +04:00
return NULL ;
2008-12-25 04:03:22 +03:00
2006-07-11 22:01:26 +04:00
for ( i = 0 ; i < num_ace ; i + + ) {
char * end_acl = strchr_m ( pacl , ' , ' ) ;
fstring acl_string ;
strncpy ( acl_string , pacl , MIN ( PTR_DIFF ( end_acl , pacl ) , sizeof ( fstring ) - 1 ) ) ;
acl_string [ MIN ( PTR_DIFF ( end_acl , pacl ) , sizeof ( fstring ) - 1 ) ] = ' \0 ' ;
2008-12-25 04:03:22 +03:00
2007-02-18 04:31:50 +03:00
if ( ! parse_ace ( & ace [ i ] , acl_string ) )
2006-07-11 22:01:26 +04:00
return NULL ;
pacl = end_acl ;
pacl + + ;
}
2008-12-25 04:03:22 +03:00
2007-02-18 04:31:50 +03:00
if ( ! ( acl = make_sec_acl ( mem_ctx , NT4_ACL_REVISION , num_ace , ace ) ) )
2006-07-11 22:01:26 +04:00
return NULL ;
2008-12-25 04:03:22 +03:00
sd = make_sec_desc ( mem_ctx , SEC_DESC_REVISION , SEC_DESC_SELF_RELATIVE ,
2007-02-18 04:31:50 +03:00
NULL , NULL , NULL , acl , sd_size ) ;
2006-07-11 22:01:26 +04:00
return sd ;
}
2007-02-18 04:31:50 +03:00
/* add an ACE to a list of ACEs in a SEC_ACL */
2007-10-19 04:40:25 +04:00
static bool add_ace ( TALLOC_CTX * mem_ctx , SEC_ACL * * the_acl , SEC_ACE * ace )
2007-02-18 04:31:50 +03:00
{
SEC_ACL * new_ace ;
SEC_ACE * aces ;
if ( ! * the_acl ) {
return ( ( ( * the_acl ) = make_sec_acl ( mem_ctx , 3 , 1 , ace ) ) ! = NULL ) ;
}
if ( ! ( aces = SMB_CALLOC_ARRAY ( SEC_ACE , 1 + ( * the_acl ) - > num_aces ) ) ) {
return False ;
}
memcpy ( aces , ( * the_acl ) - > aces , ( * the_acl ) - > num_aces * sizeof ( SEC_ACE ) ) ;
memcpy ( aces + ( * the_acl ) - > num_aces , ace , sizeof ( SEC_ACE ) ) ;
new_ace = make_sec_acl ( mem_ctx , ( * the_acl ) - > revision , 1 + ( * the_acl ) - > num_aces , aces ) ;
SAFE_FREE ( aces ) ;
( * the_acl ) = new_ace ;
return True ;
}
/* The MSDN is contradictory over the ordering of ACE entries in an ACL.
However NT4 gives a " The information may have been modified by a
computer running Windows NT 5.0 " if denied ACEs do not appear before
allowed ACEs . */
static int ace_compare ( SEC_ACE * ace1 , SEC_ACE * ace2 )
{
2008-12-25 04:03:22 +03:00
if ( sec_ace_equal ( ace1 , ace2 ) )
2007-02-18 04:31:50 +03:00
return 0 ;
2008-12-25 04:03:22 +03:00
if ( ace1 - > type ! = ace2 - > type )
2007-02-18 04:31:50 +03:00
return ace2 - > type - ace1 - > type ;
2008-12-25 04:03:22 +03:00
if ( sid_compare ( & ace1 - > trustee , & ace2 - > trustee ) )
2007-02-18 04:31:50 +03:00
return sid_compare ( & ace1 - > trustee , & ace2 - > trustee ) ;
2008-12-25 04:03:22 +03:00
if ( ace1 - > flags ! = ace2 - > flags )
2007-02-18 04:31:50 +03:00
return ace1 - > flags - ace2 - > flags ;
2008-12-25 04:03:22 +03:00
if ( ace1 - > access_mask ! = ace2 - > access_mask )
2007-02-18 04:31:50 +03:00
return ace1 - > access_mask - ace2 - > access_mask ;
2008-12-25 04:03:22 +03:00
if ( ace1 - > size ! = ace2 - > size )
2007-02-18 04:31:50 +03:00
return ace1 - > size - ace2 - > size ;
return memcmp ( ace1 , ace2 , sizeof ( SEC_ACE ) ) ;
}
static void sort_acl ( SEC_ACL * the_acl )
{
uint32 i ;
if ( ! the_acl ) return ;
qsort ( the_acl - > aces , the_acl - > num_aces , sizeof ( the_acl - > aces [ 0 ] ) , QSORT_CAST ace_compare ) ;
for ( i = 1 ; i < the_acl - > num_aces ; ) {
if ( sec_ace_equal ( & the_acl - > aces [ i - 1 ] , & the_acl - > aces [ i ] ) ) {
int j ;
for ( j = i ; j < the_acl - > num_aces - 1 ; j + + ) {
the_acl - > aces [ j ] = the_acl - > aces [ j + 1 ] ;
}
the_acl - > num_aces - - ;
} else {
i + + ;
}
}
}
static int change_share_sec ( TALLOC_CTX * mem_ctx , const char * sharename , char * the_acl , enum acl_mode mode )
{
2008-09-16 04:39:43 +04:00
SEC_DESC * sd = NULL ;
2007-02-18 04:31:50 +03:00
SEC_DESC * old = NULL ;
size_t sd_size = 0 ;
uint32 i , j ;
2008-12-25 04:03:22 +03:00
2008-12-29 04:22:28 +03:00
if ( mode ! = SMB_ACL_SET & & mode ! = SMB_SD_DELETE ) {
2007-02-18 04:31:50 +03:00
if ( ! ( old = get_share_security ( mem_ctx , sharename , & sd_size ) ) ) {
2008-12-29 04:22:28 +03:00
fprintf ( stderr , " Unable to retrieve permissions for share "
" [%s] \n " , sharename ) ;
2007-02-18 04:31:50 +03:00
return - 1 ;
}
}
2008-12-29 04:22:28 +03:00
if ( ( mode ! = SMB_ACL_VIEW & & mode ! = SMB_SD_DELETE ) & &
! ( sd = parse_acl_string ( mem_ctx , the_acl , & sd_size ) ) ) {
2007-02-18 04:31:50 +03:00
fprintf ( stderr , " Failed to parse acl \n " ) ;
return - 1 ;
}
2008-12-25 04:03:22 +03:00
2007-02-18 04:31:50 +03:00
switch ( mode ) {
case SMB_ACL_VIEW :
sec_desc_print ( stdout , old ) ;
return 0 ;
case SMB_ACL_DELETE :
for ( i = 0 ; sd - > dacl & & i < sd - > dacl - > num_aces ; i + + ) {
2007-10-19 04:40:25 +04:00
bool found = False ;
2007-02-18 04:31:50 +03:00
for ( j = 0 ; old - > dacl & & j < old - > dacl - > num_aces ; j + + ) {
if ( sec_ace_equal ( & sd - > dacl - > aces [ i ] , & old - > dacl - > aces [ j ] ) ) {
uint32 k ;
for ( k = j ; k < old - > dacl - > num_aces - 1 ; k + + ) {
old - > dacl - > aces [ k ] = old - > dacl - > aces [ k + 1 ] ;
}
old - > dacl - > num_aces - - ;
found = True ;
break ;
}
}
if ( ! found ) {
printf ( " ACL for ACE: " ) ;
print_ace ( stdout , & sd - > dacl - > aces [ i ] ) ;
printf ( " not found \n " ) ;
}
}
break ;
case SMB_ACL_MODIFY :
for ( i = 0 ; sd - > dacl & & i < sd - > dacl - > num_aces ; i + + ) {
2007-10-19 04:40:25 +04:00
bool found = False ;
2007-02-18 04:31:50 +03:00
for ( j = 0 ; old - > dacl & & j < old - > dacl - > num_aces ; j + + ) {
if ( sid_equal ( & sd - > dacl - > aces [ i ] . trustee ,
& old - > dacl - > aces [ j ] . trustee ) ) {
old - > dacl - > aces [ j ] = sd - > dacl - > aces [ i ] ;
found = True ;
}
}
if ( ! found ) {
2007-12-15 23:53:26 +03:00
printf ( " ACL for SID %s not found \n " ,
sid_string_tos ( & sd - > dacl - > aces [ i ] . trustee ) ) ;
2007-02-18 04:31:50 +03:00
}
}
if ( sd - > owner_sid ) {
old - > owner_sid = sd - > owner_sid ;
}
if ( sd - > group_sid ) {
old - > group_sid = sd - > group_sid ;
}
break ;
case SMB_ACL_ADD :
for ( i = 0 ; sd - > dacl & & i < sd - > dacl - > num_aces ; i + + ) {
add_ace ( mem_ctx , & old - > dacl , & sd - > dacl - > aces [ i ] ) ;
}
break ;
case SMB_ACL_SET :
old = sd ;
break ;
2008-12-29 04:22:28 +03:00
case SMB_SD_DELETE :
if ( ! delete_share_security ( sharename ) ) {
fprintf ( stderr , " Failed to delete security descriptor for "
" share [%s] \n " , sharename ) ;
return - 1 ;
}
return 0 ;
2007-02-18 04:31:50 +03:00
}
/* Denied ACE entries must come before allowed ones */
sort_acl ( old - > dacl ) ;
if ( ! set_share_security ( sharename , old ) ) {
fprintf ( stderr , " Failed to store acl for share [%s] \n " , sharename ) ;
return 2 ;
}
return 0 ;
}
2006-07-11 22:01:26 +04:00
/********************************************************************
main program
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int main ( int argc , const char * argv [ ] )
{
int opt ;
2007-02-18 04:31:50 +03:00
int retval = 0 ;
enum acl_mode mode = SMB_ACL_SET ;
2006-07-11 22:01:26 +04:00
static char * the_acl = NULL ;
fstring sharename ;
2007-10-19 04:40:25 +04:00
bool force_acl = False ;
2006-07-11 22:01:26 +04:00
int snum ;
poptContext pc ;
2007-10-19 04:40:25 +04:00
bool initialize_sid = False ;
2006-07-11 22:01:26 +04:00
struct poptOption long_options [ ] = {
POPT_AUTOHELP
2008-12-29 04:22:28 +03:00
{ " remove " , ' r ' , POPT_ARG_STRING , & the_acl , ' r ' , " Remove ACEs " , " ACL " } ,
{ " modify " , ' m ' , POPT_ARG_STRING , & the_acl , ' m ' , " Modify existing ACEs " , " ACL " } ,
{ " add " , ' a ' , POPT_ARG_STRING , & the_acl , ' a ' , " Add ACEs " , " ACL " } ,
{ " replace " , ' R ' , POPT_ARG_STRING , & the_acl , ' R ' , " Overwrite share permission ACL " , " ACLS " } ,
{ " delete " , ' D ' , POPT_ARG_NONE , NULL , ' D ' , " Delete the entire security descriptor " } ,
2006-07-11 22:01:26 +04:00
{ " view " , ' v ' , POPT_ARG_NONE , NULL , ' v ' , " View current share permissions " } ,
{ " machine-sid " , ' M ' , POPT_ARG_NONE , NULL , ' M ' , " Initialize the machine SID " } ,
{ " force " , ' F ' , POPT_ARG_NONE , NULL , ' F ' , " Force storing the ACL " , " ACLS " } ,
POPT_COMMON_SAMBA
{ NULL }
} ;
2007-09-04 09:39:06 +04:00
if ( ! ( ctx = talloc_stackframe ( ) ) ) {
2006-07-11 22:01:26 +04:00
fprintf ( stderr , " Failed to initialize talloc context! \n " ) ;
return - 1 ;
}
/* set default debug level to 1 regardless of what smb.conf sets */
setup_logging ( " sharesec " , True ) ;
DEBUGLEVEL_CLASS [ DBGC_ALL ] = 1 ;
dbf = x_stderr ;
x_setbuf ( x_stderr , NULL ) ;
2007-02-18 04:31:50 +03:00
pc = poptGetContext ( " sharesec " , argc , argv , long_options , 0 ) ;
2008-12-25 04:03:22 +03:00
2006-07-11 22:01:26 +04:00
poptSetOtherOptionHelp ( pc , " sharename \n " ) ;
while ( ( opt = poptGetNextOpt ( pc ) ) ! = - 1 ) {
switch ( opt ) {
case ' r ' :
the_acl = smb_xstrdup ( poptGetOptArg ( pc ) ) ;
2007-02-18 04:31:50 +03:00
mode = SMB_ACL_DELETE ;
2006-07-11 22:01:26 +04:00
break ;
case ' m ' :
the_acl = smb_xstrdup ( poptGetOptArg ( pc ) ) ;
mode = SMB_ACL_MODIFY ;
break ;
case ' a ' :
the_acl = smb_xstrdup ( poptGetOptArg ( pc ) ) ;
mode = SMB_ACL_ADD ;
break ;
2008-12-29 04:22:28 +03:00
2006-07-11 22:01:26 +04:00
case ' R ' :
the_acl = smb_xstrdup ( poptGetOptArg ( pc ) ) ;
2007-02-18 04:31:50 +03:00
mode = SMB_ACL_SET ;
2006-07-11 22:01:26 +04:00
break ;
2008-12-29 04:22:28 +03:00
case ' D ' :
mode = SMB_SD_DELETE ;
break ;
2006-07-11 22:01:26 +04:00
case ' v ' :
mode = SMB_ACL_VIEW ;
break ;
case ' F ' :
force_acl = True ;
break ;
2008-12-25 04:03:22 +03:00
2006-07-11 22:01:26 +04:00
case ' M ' :
initialize_sid = True ;
break ;
}
}
2008-12-25 04:03:22 +03:00
2007-02-18 04:31:50 +03:00
setlinebuf ( stdout ) ;
load_case_tables ( ) ;
2007-12-10 22:30:37 +03:00
lp_load ( get_dyn_CONFIGFILE ( ) , False , False , False , True ) ;
2007-02-18 04:31:50 +03:00
2006-07-11 22:01:26 +04:00
/* check for initializing secrets.tdb first */
2008-12-25 04:03:22 +03:00
2006-07-11 22:01:26 +04:00
if ( initialize_sid ) {
DOM_SID * sid = get_global_sam_sid ( ) ;
2008-12-25 04:03:22 +03:00
2006-07-11 22:01:26 +04:00
if ( ! sid ) {
fprintf ( stderr , " Failed to retrieve Machine SID! \n " ) ;
return 3 ;
}
2008-12-25 04:03:22 +03:00
2007-12-15 23:53:26 +03:00
printf ( " %s \n " , sid_string_tos ( sid ) ) ;
2006-07-11 22:01:26 +04:00
return 0 ;
}
if ( mode = = SMB_ACL_VIEW & & force_acl ) {
fprintf ( stderr , " Invalid combination of -F and -v \n " ) ;
return - 1 ;
}
/* get the sharename */
2008-12-25 04:03:22 +03:00
if ( ! poptPeekArg ( pc ) ) {
poptPrintUsage ( pc , stderr , 0 ) ;
2006-07-11 22:01:26 +04:00
return - 1 ;
}
2008-12-25 04:03:22 +03:00
2006-07-11 22:01:26 +04:00
fstrcpy ( sharename , poptGetArg ( pc ) ) ;
2008-12-25 04:03:22 +03:00
2006-07-11 22:01:26 +04:00
snum = lp_servicenumber ( sharename ) ;
2008-12-25 04:03:22 +03:00
2006-07-11 22:01:26 +04:00
if ( snum = = - 1 & & ! force_acl ) {
fprintf ( stderr , " Invalid sharename: %s \n " , sharename ) ;
return - 1 ;
}
2008-12-25 04:03:22 +03:00
2007-02-18 04:31:50 +03:00
retval = change_share_sec ( ctx , sharename , the_acl , mode ) ;
2008-12-25 04:03:22 +03:00
2006-07-11 22:01:26 +04:00
talloc_destroy ( ctx ) ;
2007-02-18 04:31:50 +03:00
return retval ;
2006-07-11 22:01:26 +04:00
}