summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--librpc/idl/security.idl19
-rw-r--r--source4/scripting/python/pyglue.c15
-rw-r--r--source4/scripting/python/samba/__init__.py15
-rw-r--r--source4/scripting/python/samba/netcmd/__init__.py2
-rw-r--r--source4/scripting/python/samba/netcmd/dsacl.py174
-rw-r--r--source4/scripting/python/samba/netcmd/netacl.py36
-rw-r--r--source4/scripting/python/samba/netcmd/ntacl.py2
7 files changed, 260 insertions, 3 deletions
diff --git a/librpc/idl/security.idl b/librpc/idl/security.idl
index 186c2bcb6a..e7ae8541cc 100644
--- a/librpc/idl/security.idl
+++ b/librpc/idl/security.idl
@@ -479,4 +479,21 @@ interface security
SEC_OWNER_FROM_PARENT = 0x00000008,
SEC_GROUP_FROM_PARENT = 0x00000010
} security_autoinherit;
-}
+
+ /***************************************************************/
+ /* Extended right guids */
+
+ const string GUID_DRS_ALLOCATE_RIDS = "1abd7cf8-0a99-11d1-adbb-00c04fd8d5cd";
+ const string GUID_DRS_CHANGE_DOMAIN_MASTER = "014bf69c-7b3b-11d1-85f6-08002be74fab";
+ const string GUID_DRS_CHANGE_INFR_MASTER = "cc17b1fb-33d9-11d2-97d4-00c04fd8d5cd";
+ const string GUID_DRS_CHANGE_PDC = "bae50096-4752-11d1-9052-00c04fc2d4cf";
+ const string GUID_DRS_CHANGE_RID_MASTER = "d58d5f36-0a98-11d1-adbb-00c04fd8d5cd";
+ const string GUID_DRS_CHANGE_SCHEMA_MASTER = "e12b56b6-0a95-11d1-adbb-00c04fd8d5cd";
+ const string GUID_DRS_GET_CHANGES = "1131f6aa-9c07-11d1-f79f-00c04fc2dcd2";
+ const string GUID_DRS_GET_ALL_CHANGES = "1131f6ad-9c07-11d1-f79f-00c04fc2dcd2";
+ const string GUID_DRS_GET_FILTERED_ATTRIBUTES = "89e95b76-444d-4c62-991a-0facbeda640c";
+ const string GUID_DRS_MANAGE_TOPOLOGY = "1131f6ac-9c07-11d1-f79f-00c04fc2dcd2";
+ const string GUID_DRS_MONITOR_TOPOLOGY = "f98340fb-7c5b-4cdb-a00b-2ebdfa115a96";
+ const string GUID_DRS_REPL_SYNCRONIZE = "1131f6ab-9c07-11d1-f79f-00c04fc2dcd2";
+ const string GUID_DRS_RO_REPL_SECRET_SYNC = "1131f6ae-9c07-11d1-f79f-00c04fc2dcd2";
+} \ No newline at end of file
diff --git a/source4/scripting/python/pyglue.c b/source4/scripting/python/pyglue.c
index c64f08e13e..e28406a0d6 100644
--- a/source4/scripting/python/pyglue.c
+++ b/source4/scripting/python/pyglue.c
@@ -772,6 +772,21 @@ void initglue(void)
PyModule_AddObject(m, "SECINFO_DACL", PyInt_FromLong(SECINFO_DACL));
PyModule_AddObject(m, "SECINFO_SACL", PyInt_FromLong(SECINFO_SACL));
+ /* control access rights guids */
+ PyModule_AddObject(m, "GUID_DRS_ALLOCATE_RIDS", PyString_FromString(GUID_DRS_ALLOCATE_RIDS));
+ PyModule_AddObject(m, "GUID_DRS_CHANGE_DOMAIN_MASTER", PyString_FromString(GUID_DRS_CHANGE_DOMAIN_MASTER));
+ PyModule_AddObject(m, "GUID_DRS_CHANGE_INFR_MASTER", PyString_FromString(GUID_DRS_CHANGE_INFR_MASTER));
+ PyModule_AddObject(m, "GUID_DRS_CHANGE_PDC", PyString_FromString(GUID_DRS_CHANGE_PDC));
+ PyModule_AddObject(m, "GUID_DRS_CHANGE_RID_MASTER", PyString_FromString(GUID_DRS_CHANGE_RID_MASTER));
+ PyModule_AddObject(m, "GUID_DRS_CHANGE_SCHEMA_MASTER", PyString_FromString(GUID_DRS_CHANGE_SCHEMA_MASTER));
+ PyModule_AddObject(m, "GUID_DRS_GET_CHANGES", PyString_FromString(GUID_DRS_GET_CHANGES));
+ PyModule_AddObject(m, "GUID_DRS_GET_ALL_CHANGES", PyString_FromString(GUID_DRS_GET_ALL_CHANGES));
+ PyModule_AddObject(m, "GUID_DRS_GET_FILTERED_ATTRIBUTES", PyString_FromString(GUID_DRS_GET_FILTERED_ATTRIBUTES));
+ PyModule_AddObject(m, "GUID_DRS_MANAGE_TOPOLOGY", PyString_FromString(GUID_DRS_MANAGE_TOPOLOGY));
+ PyModule_AddObject(m, "GUID_DRS_MONITOR_TOPOLOGY", PyString_FromString(GUID_DRS_MONITOR_TOPOLOGY));
+ PyModule_AddObject(m, "GUID_DRS_REPL_SYNCRONIZE", PyString_FromString(GUID_DRS_REPL_SYNCRONIZE));
+ PyModule_AddObject(m, "GUID_DRS_RO_REPL_SECRET_SYNC", PyString_FromString(GUID_DRS_RO_REPL_SECRET_SYNC));
+
/* one of the most annoying things about python scripts is
that they don't die when you hit control-C. This fixes that
sillyness. As we do all database operations using
diff --git a/source4/scripting/python/samba/__init__.py b/source4/scripting/python/samba/__init__.py
index 9cc224b562..24bb45a003 100644
--- a/source4/scripting/python/samba/__init__.py
+++ b/source4/scripting/python/samba/__init__.py
@@ -442,3 +442,18 @@ SECINFO_GROUP = glue.SECINFO_GROUP
SECINFO_DACL = glue.SECINFO_DACL
SECINFO_SACL = glue.SECINFO_SACL
+#control access rights guids
+GUID_DRS_ALLOCATE_RIDS = glue.GUID_DRS_ALLOCATE_RIDS
+GUID_DRS_CHANGE_DOMAIN_MASTER = glue.GUID_DRS_CHANGE_DOMAIN_MASTER
+GUID_DRS_CHANGE_INFR_MASTER = glue.GUID_DRS_CHANGE_INFR_MASTER
+GUID_DRS_CHANGE_PDC = glue.GUID_DRS_CHANGE_PDC
+GUID_DRS_CHANGE_RID_MASTER = glue.GUID_DRS_CHANGE_RID_MASTER
+GUID_DRS_CHANGE_SCHEMA_MASTER = glue.GUID_DRS_CHANGE_SCHEMA_MASTER
+GUID_DRS_GET_CHANGES = glue.GUID_DRS_GET_CHANGES
+GUID_DRS_GET_ALL_CHANGES = glue.GUID_DRS_GET_ALL_CHANGES
+GUID_DRS_GET_FILTERED_ATTRIBUTES = glue.GUID_DRS_GET_FILTERED_ATTRIBUTES
+GUID_DRS_MANAGE_TOPOLOGY = glue.GUID_DRS_MANAGE_TOPOLOGY
+GUID_DRS_MONITOR_TOPOLOGY = glue.GUID_DRS_MONITOR_TOPOLOGY
+GUID_DRS_REPL_SYNCRONIZE = glue.GUID_DRS_REPL_SYNCRONIZE
+GUID_DRS_RO_REPL_SECRET_SYNC = glue.GUID_DRS_RO_REPL_SECRET_SYNC
+
diff --git a/source4/scripting/python/samba/netcmd/__init__.py b/source4/scripting/python/samba/netcmd/__init__.py
index df0154ec4f..f09828e6bb 100644
--- a/source4/scripting/python/samba/netcmd/__init__.py
+++ b/source4/scripting/python/samba/netcmd/__init__.py
@@ -143,7 +143,7 @@ from samba.netcmd.enableaccount import cmd_enableaccount
commands["enableaccount"] = cmd_enableaccount()
from samba.netcmd.newuser import cmd_newuser
commands["newuser"] = cmd_newuser()
-from samba.netcmd.ntacl import cmd_acl
+from samba.netcmd.netacl import cmd_acl
commands["acl"] = cmd_acl()
from samba.netcmd.fsmo import cmd_fsmo
commands["fsmo"] = cmd_fsmo()
diff --git a/source4/scripting/python/samba/netcmd/dsacl.py b/source4/scripting/python/samba/netcmd/dsacl.py
new file mode 100644
index 0000000000..d5d39aa69a
--- /dev/null
+++ b/source4/scripting/python/samba/netcmd/dsacl.py
@@ -0,0 +1,174 @@
+#!/usr/bin/python
+#
+# 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/>.
+#
+
+from samba.credentials import DONT_USE_KERBEROS
+import samba.getopt as options
+from samba.dcerpc import security
+from samba import Ldb
+from samba.samdb import SamDB
+from samba.ndr import ndr_unpack, ndr_pack
+from samba 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
+
+import ldb
+from ldb import SCOPE_BASE, SCOPE_SUBTREE
+import os
+import re
+
+from samba.auth import system_session
+from samba.netcmd import (
+ Command,
+ CommandError,
+ SuperCommand,
+ Option,
+ )
+
+class cmd_ds_acl_set(Command):
+ """Modify access list on a directory object"""
+
+ synopsis = "set --objectdn=objectdn --car=control right --action=[deny|allow] --trusteedn=trustee-dn"
+ car_help = """ The access control right to allow or deny """
+
+ takes_optiongroups = {
+ "sambaopts": options.SambaOptions,
+ "credopts": options.CredentialsOptions,
+ "versionopts": options.VersionOptions,
+ }
+
+ takes_options = [
+ Option("--host", help="LDB URL for database or target server", type=str),
+ 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"],
+ help="""Deny or allow access"""),
+ Option("--objectdn", help="DN of the object whose SD to modify", type="string"),
+ Option("--trusteedn", help="DN of the entity that gets access", type="string"),
+ ]
+
+ 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 modify_descriptor(self, samdb, object_dn, desc, controls=None):
+ assert(isinstance(desc, security.descriptor))
+ m = ldb.Message()
+ m.dn = ldb.Dn(samdb, object_dn)
+ m["nTSecurityDescriptor"]= ldb.MessageElement(
+ (ndr_pack(desc)), ldb.FLAG_MOD_REPLACE,
+ "nTSecurityDescriptor")
+ samdb.modify(m)
+
+ def read_descriptor(self, samdb, object_dn):
+ res = samdb.search(base=object_dn, scope=SCOPE_BASE, attrs=["nTSecurityDescriptor"])
+ # we should theoretically always have an SD
+ assert(len(res) == 1)
+ desc = res[0]["nTSecurityDescriptor"][0]
+ return ndr_unpack(security.descriptor, desc)
+
+ def get_domain_sid(self, samdb):
+ res = samdb.search(base=SamDB.domain_dn(samdb), expression="(objectClass=*)", scope=SCOPE_BASE)
+ return ndr_unpack( security.dom_sid,res[0]["objectSid"][0])
+
+ #add new ace explicitly
+ def add_ace(self, samdb, object_dn, new_ace):
+ desc = self.read_descriptor(samdb, object_dn)
+ desc_sddl = desc.as_sddl(self.get_domain_sid(samdb))
+ #TODO add bindings for descriptor manipulation and get rid of this
+ desc_aces = re.findall("\(.*?\)", desc_sddl)
+ for ace in desc_aces:
+ if ("ID" in ace):
+ desc_sddl = desc_sddl.replace(ace, "")
+ if new_ace in desc_sddl:
+ return
+ if desc_sddl.find("(") >= 0:
+ desc_sddl = desc_sddl[:desc_sddl.index("(")] + new_ace + desc_sddl[desc_sddl.index("("):]
+ else:
+ desc_sddl = desc_sddl + new_ace
+ desc = security.descriptor.from_sddl(desc_sddl, self.get_domain_sid(samdb))
+ self.modify_descriptor(samdb, object_dn, desc)
+
+ def print_new_acl(self, samdb, object_dn):
+ desc = self.read_descriptor(samdb, object_dn)
+ desc_sddl = desc.as_sddl(self.get_domain_sid(samdb))
+ print "new descriptor for %s:" % object_dn
+ print desc_sddl
+
+ def run(self, car, action, objectdn, trusteedn,
+ host=None, credopts=None, sambaopts=None, versionopts=None):
+ lp = sambaopts.get_loadparm()
+ creds = credopts.get_credentials(lp)
+
+ if car == None or action == None or objectdn == None or trusteedn == None:
+ return self.usage()
+
+ if host is not None:
+ url = host
+ else:
+ url = lp.get("sam database")
+
+ samdb = SamDB(url=url, session_info=system_session(),
+ credentials=creds, lp=lp)
+ 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,
+ }
+ sid = self.find_trustee_sid(samdb, trusteedn)
+ if action == "allow":
+ 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)
+
+ self.print_new_acl(samdb, objectdn)
+ self.add_ace(samdb, objectdn, new_ace)
+ self.print_new_acl(samdb, objectdn)
+
+class cmd_ds_acl(SuperCommand):
+ """DS ACLs manipulation"""
+
+ subcommands = {}
+ subcommands["set"] = cmd_ds_acl_set()
diff --git a/source4/scripting/python/samba/netcmd/netacl.py b/source4/scripting/python/samba/netcmd/netacl.py
new file mode 100644
index 0000000000..48e353a75f
--- /dev/null
+++ b/source4/scripting/python/samba/netcmd/netacl.py
@@ -0,0 +1,36 @@
+#!/usr/bin/python
+#
+# Manipulate ACLs
+#
+# Copyright (C) Matthieu Patou <mat@matws.net> 2010
+# 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
+import os
+
+from samba.netcmd import (
+ SuperCommand,
+ )
+from samba.netcmd.ntacl import cmd_nt_acl
+from samba.netcmd.dsacl import cmd_ds_acl
+
+class cmd_acl(SuperCommand):
+ """NT ACLs manipulation"""
+
+ subcommands = {}
+ subcommands["nt"] = cmd_nt_acl()
+ subcommands["ds"] = cmd_ds_acl()
diff --git a/source4/scripting/python/samba/netcmd/ntacl.py b/source4/scripting/python/samba/netcmd/ntacl.py
index 9b25ca2ba3..ebb66864d7 100644
--- a/source4/scripting/python/samba/netcmd/ntacl.py
+++ b/source4/scripting/python/samba/netcmd/ntacl.py
@@ -110,7 +110,7 @@ class cmd_acl_get(Command):
acl.dump()
-class cmd_acl(SuperCommand):
+class cmd_nt_acl(SuperCommand):
"""NT ACLs manipulation"""
subcommands = {}