1 # Manipulate ACLs on directory objects
3 # Copyright (C) Nadezhda Ivanova <nivanova@samba.org> 2010
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 3 of the License, or
8 # (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program. If not, see <http://www.gnu.org/licenses/>.
19 import samba
.getopt
as options
20 from samba
import sd_utils
21 from samba
.dcerpc
import security
22 from samba
.samdb
import SamDB
23 from samba
.ndr
import ndr_unpack
, ndr_pack
24 from samba
.dcerpc
.security
import (
25 GUID_DRS_ALLOCATE_RIDS
, GUID_DRS_CHANGE_DOMAIN_MASTER
,
26 GUID_DRS_CHANGE_INFR_MASTER
, GUID_DRS_CHANGE_PDC
,
27 GUID_DRS_CHANGE_RID_MASTER
, GUID_DRS_CHANGE_SCHEMA_MASTER
,
28 GUID_DRS_GET_CHANGES
, GUID_DRS_GET_ALL_CHANGES
,
29 GUID_DRS_GET_FILTERED_ATTRIBUTES
, GUID_DRS_MANAGE_TOPOLOGY
,
30 GUID_DRS_MONITOR_TOPOLOGY
, GUID_DRS_REPL_SYNCRONIZE
,
31 GUID_DRS_RO_REPL_SECRET_SYNC
)
35 from ldb
import SCOPE_BASE
38 from samba
.auth
import system_session
39 from samba
.netcmd
import (
46 class cmd_dsacl_base(Command
):
47 """Base class for DSACL commands."""
49 synopsis
= "%prog [options]"
51 takes_optiongroups
= {
52 "sambaopts": options
.SambaOptions
,
53 "credopts": options
.CredentialsOptions
,
54 "versionopts": options
.VersionOptions
,
57 def print_acl(self
, sd_helper
, object_dn
, prefix
=''):
58 desc_sddl
= sd_helper
.get_sd_as_sddl(object_dn
)
59 self
.outf
.write("%sdescriptor for %s:\n" % (prefix
, object_dn
))
60 self
.outf
.write(desc_sddl
+ "\n")
63 class cmd_dsacl_set(cmd_dsacl_base
):
64 """Modify access list on a directory object."""
66 car_help
= """ The access control right to allow or deny """
69 Option("-H", "--URL", help="LDB URL for database or target server",
70 type=str, metavar
="URL", dest
="H"),
71 Option("--car", type="choice", choices
=["change-rid",
73 "change-infrastructure",
79 "get-changes-filtered",
83 "ro-repl-secret-sync"],
85 Option("--action", type="choice", choices
=["allow", "deny"],
86 help="""Deny or allow access"""),
87 Option("--objectdn", help="DN of the object whose SD to modify",
89 Option("--trusteedn", help="DN of the entity that gets access",
91 Option("--sddl", help="An ACE or group of ACEs to be added on the object",
95 def find_trustee_sid(self
, samdb
, trusteedn
):
96 res
= samdb
.search(base
=trusteedn
, expression
="(objectClass=*)",
99 return ndr_unpack(security
.dom_sid
, res
[0]["objectSid"][0])
101 def add_ace(self
, sd_helper
, object_dn
, new_ace
):
102 """Add new ace explicitly."""
103 ai
,ii
= sd_helper
.dacl_prepend_aces(object_dn
, new_ace
)
105 sddl
= ace
.as_sddl(sd_helper
.domain_sid
)
106 self
.outf
.write("WARNING: ignored INHERITED_ACE (%s).\n" % sddl
)
108 sddl
= ace
.as_sddl(sd_helper
.domain_sid
)
109 self
.outf
.write("WARNING: (%s) was already found in the current security descriptor.\n" % sddl
)
111 def run(self
, car
, action
, objectdn
, trusteedn
, sddl
,
112 H
=None, credopts
=None, sambaopts
=None, versionopts
=None):
113 lp
= sambaopts
.get_loadparm()
114 creds
= credopts
.get_credentials(lp
)
116 if sddl
is None and (car
is None or action
is None
117 or objectdn
is None or trusteedn
is None):
120 samdb
= SamDB(url
=H
, session_info
=system_session(),
121 credentials
=creds
, lp
=lp
)
122 sd_helper
= sd_utils
.SDUtils(samdb
)
123 cars
= {'change-rid': GUID_DRS_CHANGE_RID_MASTER
,
124 'change-pdc': GUID_DRS_CHANGE_PDC
,
125 'change-infrastructure': GUID_DRS_CHANGE_INFR_MASTER
,
126 'change-schema': GUID_DRS_CHANGE_SCHEMA_MASTER
,
127 'change-naming': GUID_DRS_CHANGE_DOMAIN_MASTER
,
128 'allocate_rids': GUID_DRS_ALLOCATE_RIDS
,
129 'get-changes': GUID_DRS_GET_CHANGES
,
130 'get-changes-all': GUID_DRS_GET_ALL_CHANGES
,
131 'get-changes-filtered': GUID_DRS_GET_FILTERED_ATTRIBUTES
,
132 'topology-manage': GUID_DRS_MANAGE_TOPOLOGY
,
133 'topology-monitor': GUID_DRS_MONITOR_TOPOLOGY
,
134 'repl-sync': GUID_DRS_REPL_SYNCRONIZE
,
135 'ro-repl-secret-sync': GUID_DRS_RO_REPL_SECRET_SYNC
,
137 sid
= self
.find_trustee_sid(samdb
, trusteedn
)
140 elif action
== "allow":
141 new_ace
= "(OA;;CR;%s;;%s)" % (cars
[car
], str(sid
))
142 elif action
== "deny":
143 new_ace
= "(OD;;CR;%s;;%s)" % (cars
[car
], str(sid
))
145 raise CommandError("Wrong argument '%s'!" % action
)
147 self
.print_acl(sd_helper
, objectdn
, prefix
='old ')
148 self
.add_ace(sd_helper
, objectdn
, new_ace
)
149 self
.print_acl(sd_helper
, objectdn
, prefix
='new ')
152 class cmd_dsacl_get(cmd_dsacl_base
):
153 """Print access list on a directory object."""
156 Option("-H", "--URL", help="LDB URL for database or target server",
157 type=str, metavar
="URL", dest
="H"),
158 Option("--objectdn", help="DN of the object whose SD to modify",
162 def run(self
, objectdn
,
163 H
=None, credopts
=None, sambaopts
=None, versionopts
=None):
164 lp
= sambaopts
.get_loadparm()
165 creds
= credopts
.get_credentials(lp
)
167 samdb
= SamDB(url
=H
, session_info
=system_session(),
168 credentials
=creds
, lp
=lp
)
169 sd_helper
= sd_utils
.SDUtils(samdb
)
170 self
.print_acl(sd_helper
, objectdn
)
173 class cmd_dsacl_delete(cmd_dsacl_base
):
174 """Delete an access list entry on a directory object."""
177 Option("-H", "--URL", help="LDB URL for database or target server",
178 type=str, metavar
="URL", dest
="H"),
179 Option("--objectdn", help="DN of the object whose SD to modify",
181 Option("--sddl", help="An ACE or group of ACEs to be deleted from the object",
185 def run(self
, objectdn
, sddl
, H
=None, credopts
=None, sambaopts
=None, versionopts
=None):
186 lp
= sambaopts
.get_loadparm()
187 creds
= credopts
.get_credentials(lp
)
189 if sddl
is None or objectdn
is None:
192 samdb
= SamDB(url
=H
, session_info
=system_session(),
193 credentials
=creds
, lp
=lp
)
194 sd_helper
= sd_utils
.SDUtils(samdb
)
196 self
.print_acl(sd_helper
, objectdn
, prefix
='old ')
197 self
.delete_ace(sd_helper
, objectdn
, sddl
)
198 self
.print_acl(sd_helper
, objectdn
, prefix
='new ')
200 def delete_ace(self
, sd_helper
, object_dn
, delete_aces
):
201 """Delete ace explicitly."""
202 di
,ii
= sd_helper
.dacl_delete_aces(object_dn
, delete_aces
)
204 sddl
= ace
.as_sddl(sd_helper
.domain_sid
)
205 self
.outf
.write("WARNING: ignored INHERITED_ACE (%s).\n" % sddl
)
207 sddl
= ace
.as_sddl(sd_helper
.domain_sid
)
208 self
.outf
.write("WARNING: (%s) was not found in the current security descriptor.\n" % sddl
)
211 class cmd_dsacl(SuperCommand
):
212 """DS ACLs manipulation."""
215 subcommands
["set"] = cmd_dsacl_set()
216 subcommands
["get"] = cmd_dsacl_get()
217 subcommands
["delete"] = cmd_dsacl_delete()