2010-03-16 14:06:08 +03:00
# Manipulate ACLs on directory objects
#
# Copyright (C) Nadezhda Ivanova <nivanova@samba.org> 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/>.
#
import samba . getopt as options
2023-03-16 20:32:49 +03:00
from samba import sd_utils
2010-03-16 14:06:08 +03:00
from samba . dcerpc import security
from samba . samdb import SamDB
from samba . ndr import ndr_unpack , ndr_pack
2010-04-04 01:18:23 +04:00
from samba . dcerpc . security import (
GUID_DRS_ALLOCATE_RIDS , GUID_DRS_CHANGE_DOMAIN_MASTER ,
GUID_DRS_CHANGE_INFR_MASTER , GUID_DRS_CHANGE_PDC ,
GUID_DRS_CHANGE_RID_MASTER , GUID_DRS_CHANGE_SCHEMA_MASTER ,
GUID_DRS_GET_CHANGES , GUID_DRS_GET_ALL_CHANGES ,
GUID_DRS_GET_FILTERED_ATTRIBUTES , GUID_DRS_MANAGE_TOPOLOGY ,
GUID_DRS_MONITOR_TOPOLOGY , GUID_DRS_REPL_SYNCRONIZE ,
GUID_DRS_RO_REPL_SECRET_SYNC )
2010-03-16 14:06:08 +03:00
import ldb
2010-04-04 01:18:23 +04:00
from ldb import SCOPE_BASE
2010-03-16 14:06:08 +03:00
import re
from samba . auth import system_session
from samba . netcmd import (
Command ,
CommandError ,
SuperCommand ,
Option ,
2018-07-30 09:14:37 +03:00
)
2010-03-16 14:06:08 +03:00
2022-09-15 11:20:04 +03:00
class cmd_dsacl_base ( Command ) :
""" Base class for DSACL commands. """
2010-03-16 14:06:08 +03:00
2011-10-14 01:27:22 +04:00
synopsis = " % prog [options] "
2010-03-16 14:06:08 +03:00
2012-02-06 19:33:38 +04:00
takes_optiongroups = {
" sambaopts " : options . SambaOptions ,
" credopts " : options . CredentialsOptions ,
" versionopts " : options . VersionOptions ,
2018-07-30 09:14:37 +03:00
}
2012-02-06 19:33:38 +04:00
2023-03-16 20:32:49 +03:00
def print_acl ( self , sd_helper , object_dn , prefix = ' ' ) :
desc_sddl = sd_helper . get_sd_as_sddl ( object_dn )
2022-09-15 11:20:04 +03:00
self . outf . write ( " %s descriptor for %s : \n " % ( prefix , object_dn ) )
self . outf . write ( desc_sddl + " \n " )
class cmd_dsacl_set ( cmd_dsacl_base ) :
""" Modify access list on a directory object. """
car_help = """ The access control right to allow or deny """
2010-03-16 14:06:08 +03:00
takes_options = [
2011-07-25 19:56:10 +04:00
Option ( " -H " , " --URL " , help = " LDB URL for database or target server " ,
type = str , metavar = " URL " , dest = " H " ) ,
2010-03-16 14:06:08 +03:00
Option ( " --car " , type = " choice " , choices = [ " change-rid " ,
" change-pdc " ,
" change-infrastructure " ,
" change-schema " ,
" change-naming " ,
" allocate_rids " ,
" get-changes " ,
" get-changes-all " ,
" get-changes-filtered " ,
" topology-manage " ,
" topology-monitor " ,
" repl-sync " ,
" ro-repl-secret-sync " ] ,
help = car_help ) ,
Option ( " --action " , type = " choice " , choices = [ " allow " , " deny " ] ,
2018-07-30 09:15:34 +03:00
help = """ Deny or allow access """ ) ,
2010-04-08 20:57:09 +04:00
Option ( " --objectdn " , help = " DN of the object whose SD to modify " ,
2018-07-30 09:16:12 +03:00
type = " string " ) ,
2010-04-08 20:57:09 +04:00
Option ( " --trusteedn " , help = " DN of the entity that gets access " ,
2018-07-30 09:16:12 +03:00
type = " string " ) ,
2011-02-10 16:04:23 +03:00
Option ( " --sddl " , help = " An ACE or group of ACEs to be added on the object " ,
2018-07-30 09:16:12 +03:00
type = " string " ) ,
2018-07-30 09:14:37 +03:00
]
2010-03-16 14:06:08 +03:00
2023-03-16 20:32:49 +03:00
def find_trustee_sid ( self , samdb , trusteedn ) :
res = samdb . search ( base = trusteedn , expression = " (objectClass=*) " ,
scope = SCOPE_BASE )
assert ( len ( res ) == 1 )
return ndr_unpack ( security . dom_sid , res [ 0 ] [ " objectSid " ] [ 0 ] )
def add_ace ( self , sd_helper , object_dn , new_ace ) :
2010-04-08 20:57:09 +04:00
""" Add new ace explicitly. """
2023-03-16 20:32:49 +03:00
ai , ii = sd_helper . dacl_prepend_aces ( object_dn , new_ace )
for ace in ii :
sddl = ace . as_sddl ( sd_helper . domain_sid )
self . outf . write ( " WARNING: ignored INHERITED_ACE ( %s ). \n " % sddl )
for ace in ai :
sddl = ace . as_sddl ( sd_helper . domain_sid )
self . outf . write ( " WARNING: ( %s ) was already found in the current security descriptor. \n " % sddl )
2010-03-16 14:06:08 +03:00
2011-02-10 16:04:23 +03:00
def run ( self , car , action , objectdn , trusteedn , sddl ,
2011-07-25 19:56:10 +04:00
H = None , credopts = None , sambaopts = None , versionopts = None ) :
2010-03-16 14:06:08 +03:00
lp = sambaopts . get_loadparm ( )
creds = credopts . get_credentials ( lp )
2011-02-10 16:04:23 +03:00
if sddl is None and ( car is None or action is None
or objectdn is None or trusteedn is None ) :
2010-03-16 14:06:08 +03:00
return self . usage ( )
2011-07-25 19:56:10 +04:00
samdb = SamDB ( url = H , session_info = system_session ( ) ,
2018-07-30 09:16:12 +03:00
credentials = creds , lp = lp )
2023-03-16 20:32:49 +03:00
sd_helper = sd_utils . SDUtils ( samdb )
2018-07-30 09:17:14 +03:00
cars = { ' change-rid ' : GUID_DRS_CHANGE_RID_MASTER ,
' change-pdc ' : GUID_DRS_CHANGE_PDC ,
' change-infrastructure ' : GUID_DRS_CHANGE_INFR_MASTER ,
' change-schema ' : GUID_DRS_CHANGE_SCHEMA_MASTER ,
' change-naming ' : GUID_DRS_CHANGE_DOMAIN_MASTER ,
' allocate_rids ' : GUID_DRS_ALLOCATE_RIDS ,
' get-changes ' : GUID_DRS_GET_CHANGES ,
' get-changes-all ' : GUID_DRS_GET_ALL_CHANGES ,
' get-changes-filtered ' : GUID_DRS_GET_FILTERED_ATTRIBUTES ,
' topology-manage ' : GUID_DRS_MANAGE_TOPOLOGY ,
' topology-monitor ' : GUID_DRS_MONITOR_TOPOLOGY ,
' repl-sync ' : GUID_DRS_REPL_SYNCRONIZE ,
' ro-repl-secret-sync ' : GUID_DRS_RO_REPL_SECRET_SYNC ,
2010-03-16 14:06:08 +03:00
}
2023-03-16 20:32:49 +03:00
sid = self . find_trustee_sid ( samdb , trusteedn )
2011-02-10 16:04:23 +03:00
if sddl :
new_ace = sddl
elif action == " allow " :
2010-03-16 14:06:08 +03:00
new_ace = " (OA;;CR; %s ;; %s ) " % ( cars [ car ] , str ( sid ) )
elif action == " deny " :
new_ace = " (OD;;CR; %s ;; %s ) " % ( cars [ car ] , str ( sid ) )
else :
raise CommandError ( " Wrong argument ' %s ' ! " % action )
2023-03-16 20:32:49 +03:00
self . print_acl ( sd_helper , objectdn , prefix = ' old ' )
self . add_ace ( sd_helper , objectdn , new_ace )
self . print_acl ( sd_helper , objectdn , prefix = ' new ' )
2010-03-16 14:06:08 +03:00
2010-04-08 20:57:09 +04:00
2022-09-15 11:20:04 +03:00
class cmd_dsacl_get ( cmd_dsacl_base ) :
2019-01-09 18:13:58 +03:00
""" Print access list on a directory object. """
takes_options = [
Option ( " -H " , " --URL " , help = " LDB URL for database or target server " ,
type = str , metavar = " URL " , dest = " H " ) ,
Option ( " --objectdn " , help = " DN of the object whose SD to modify " ,
type = " string " ) ,
]
def run ( self , objectdn ,
H = None , credopts = None , sambaopts = None , versionopts = None ) :
lp = sambaopts . get_loadparm ( )
creds = credopts . get_credentials ( lp )
samdb = SamDB ( url = H , session_info = system_session ( ) ,
credentials = creds , lp = lp )
2023-03-16 20:32:49 +03:00
sd_helper = sd_utils . SDUtils ( samdb )
self . print_acl ( sd_helper , objectdn )
2019-01-09 18:13:58 +03:00
2022-09-15 11:20:04 +03:00
class cmd_dsacl_delete ( cmd_dsacl_base ) :
2022-09-14 02:29:34 +03:00
""" Delete an access list entry on a directory object. """
takes_options = [
Option ( " -H " , " --URL " , help = " LDB URL for database or target server " ,
type = str , metavar = " URL " , dest = " H " ) ,
Option ( " --objectdn " , help = " DN of the object whose SD to modify " ,
type = " string " ) ,
Option ( " --sddl " , help = " An ACE or group of ACEs to be deleted from the object " ,
type = " string " ) ,
]
def run ( self , objectdn , sddl , H = None , credopts = None , sambaopts = None , versionopts = None ) :
lp = sambaopts . get_loadparm ( )
creds = credopts . get_credentials ( lp )
if sddl is None or objectdn is None :
return self . usage ( )
samdb = SamDB ( url = H , session_info = system_session ( ) ,
credentials = creds , lp = lp )
2023-03-16 20:32:49 +03:00
sd_helper = sd_utils . SDUtils ( samdb )
2022-09-14 02:29:34 +03:00
2023-03-16 20:32:49 +03:00
self . print_acl ( sd_helper , objectdn , prefix = ' old ' )
self . delete_ace ( sd_helper , objectdn , sddl )
self . print_acl ( sd_helper , objectdn , prefix = ' new ' )
2022-09-14 02:29:34 +03:00
2023-03-16 20:32:49 +03:00
def delete_ace ( self , sd_helper , object_dn , delete_aces ) :
2022-09-14 02:29:34 +03:00
""" Delete ace explicitly. """
2023-03-16 20:32:49 +03:00
di , ii = sd_helper . dacl_delete_aces ( object_dn , delete_aces )
for ace in ii :
sddl = ace . as_sddl ( sd_helper . domain_sid )
self . outf . write ( " WARNING: ignored INHERITED_ACE ( %s ). \n " % sddl )
for ace in di :
sddl = ace . as_sddl ( sd_helper . domain_sid )
self . outf . write ( " WARNING: ( %s ) was not found in the current security descriptor. \n " % sddl )
2022-09-14 02:29:34 +03:00
2011-08-31 01:09:53 +04:00
class cmd_dsacl ( SuperCommand ) :
2012-10-09 13:53:21 +04:00
""" DS ACLs manipulation. """
2010-03-16 14:06:08 +03:00
subcommands = { }
2011-08-31 01:09:53 +04:00
subcommands [ " set " ] = cmd_dsacl_set ( )
2019-01-09 18:13:58 +03:00
subcommands [ " get " ] = cmd_dsacl_get ( )
2022-09-14 02:29:34 +03:00
subcommands [ " delete " ] = cmd_dsacl_delete ( )