The branch, master has been updated via 01a425e samba-tool: gpo: Update copyright via 5c9ecb4 samba-tool: gpo: Improve error messages via df4a6e3 samba-tool: gpo: Add del subcommand to delete GPO via 8768f4f samba-tool: gpo: Add listcontainers subcommand to list containers using given GPO via 0365df9 samba-tool: gpo: Use utility function dc_url() to set the connection url via a9c4336 samba-tool: gpo: Refactor code using utility functions via 5ca2434 samba-tool: gpo: Add utility functions get_gpo_containers and del_gpo_link via e3828d4 s4-pysmb: Add deltree() method to remove directory and its contents via 807ff1e samba-tool: Fix indentation via e93ed5f samba-tool: gpo: Use gpo (id) instead of gpo_dn (DN) via 963f0df samba-tool: gpo: Correct the attribute name from gPlink to gPLink via 7563032 samba-tool: gpo: Fix policy DN from 3fe2c54 Fix the waf/autoconf builds to detect correctly the 32-bit or 64-bit syscall ABI on Linux.
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit 01a425e5345f4f9b3d24c8348273ede9a11fd520 Author: Amitay Isaacs <ami...@gmail.com> Date: Tue Jul 3 14:20:44 2012 +1000 samba-tool: gpo: Update copyright Autobuild-User(master): Amitay Isaacs <ami...@samba.org> Autobuild-Date(master): Tue Jul 3 09:10:21 CEST 2012 on sn-devel-104 commit 5c9ecb40829535d84a9ec329667fd396ac2b2166 Author: Amitay Isaacs <ami...@gmail.com> Date: Tue Jul 3 14:55:10 2012 +1000 samba-tool: gpo: Improve error messages Signed-off-by: Amitay Isaacs <ami...@gmail.com> commit df4a6e3a3f728f888d62b739534cde70add6437b Author: Amitay Isaacs <ami...@gmail.com> Date: Tue Jul 3 14:23:48 2012 +1000 samba-tool: gpo: Add del subcommand to delete GPO Thanks to Denis Bonnenfant <denis.bonnenf...@diderot.org> for patch. commit 8768f4fc34c0a41f63bbbd0fe81e983dd5baa0b3 Author: Amitay Isaacs <ami...@gmail.com> Date: Tue Jul 3 14:22:42 2012 +1000 samba-tool: gpo: Add listcontainers subcommand to list containers using given GPO Thanks to Denis Bonnenfant <denis.bonnenf...@diderot.org> for patch. commit 0365df93e61b44cbdd7270c48495a6b4ac251677 Author: Amitay Isaacs <ami...@gmail.com> Date: Tue Jul 3 14:17:48 2012 +1000 samba-tool: gpo: Use utility function dc_url() to set the connection url In create and fetch subcommands, we also need to know DC hostname. So first find a DC and use DC hostname to construct connection url. If ldap:// url is specified with -H, then use that to construct DC hostname. commit a9c4336733c6e76c129c71901500fb7d305ad45f Author: Amitay Isaacs <ami...@gmail.com> Date: Tue Jul 3 14:16:41 2012 +1000 samba-tool: gpo: Refactor code using utility functions commit 5ca24346bf6b58fb2f66862c4c085be0518fc435 Author: Amitay Isaacs <ami...@gmail.com> Date: Tue Jul 3 14:13:01 2012 +1000 samba-tool: gpo: Add utility functions get_gpo_containers and del_gpo_link Thanks to Denis Bonnenfant <denis.bonnenf...@diderot.org> for patch commit e3828d4ccb131750e0064f17ba599db5bd662753 Author: Amitay Isaacs <ami...@gmail.com> Date: Tue Jul 3 10:58:37 2012 +1000 s4-pysmb: Add deltree() method to remove directory and its contents Thanks to Denis Bonnenfant <denis.bonnenf...@diderot.org> for patch. commit 807ff1e3432d85e19d753909c1cdd93a52cbc296 Author: Amitay Isaacs <ami...@gmail.com> Date: Tue Jul 3 11:27:21 2012 +1000 samba-tool: Fix indentation Thanks to Denis Bonnenfant <denis.bonnenf...@diderot.org> for patch. commit e93ed5f69abca6e48dbb754acadfafc8b6dd716e Author: Amitay Isaacs <ami...@gmail.com> Date: Tue Jul 3 11:26:41 2012 +1000 samba-tool: gpo: Use gpo (id) instead of gpo_dn (DN) Thanks to Denis Bonnenfant <denis.bonnenf...@diderot.org> for patch. commit 963f0df179720240a8a6072dd7960aefd654ff5a Author: Amitay Isaacs <ami...@gmail.com> Date: Tue Jul 3 11:22:55 2012 +1000 samba-tool: gpo: Correct the attribute name from gPlink to gPLink Thanks to Denis Bonnenfant <denis.bonnenf...@diderot.org> for patch. commit 7563032acd72e5925e23fe88075e64f47bc1f86c Author: Amitay Isaacs <ami...@gmail.com> Date: Tue Jul 3 11:21:25 2012 +1000 samba-tool: gpo: Fix policy DN Thanks to Denis Bonnenfant <denis.bonnenf...@diderot.org> for patch. ----------------------------------------------------------------------- Summary of changes: source4/libcli/pysmb.c | 25 ++ source4/scripting/python/samba/netcmd/gpo.py | 295 ++++++++++++++++++------ source4/scripting/python/samba/netcmd/group.py | 4 +- source4/scripting/python/samba/samdb.py | 4 +- 4 files changed, 249 insertions(+), 79 deletions(-) Changeset truncated at 500 lines: diff --git a/source4/libcli/pysmb.c b/source4/libcli/pysmb.c index 14b05f7..1122305 100644 --- a/source4/libcli/pysmb.c +++ b/source4/libcli/pysmb.c @@ -263,6 +263,28 @@ static PyObject *py_smb_rmdir(pytalloc_Object *self, PyObject *args) } /* + * Remove a directory and all its contents + */ +static PyObject *py_smb_deltree(pytalloc_Object *self, PyObject *args) +{ + int status; + const char *dirname; + struct smb_private_data *spdata; + + if (!PyArg_ParseTuple(args, "s:deltree", &dirname)) { + return NULL; + } + + spdata = self->ptr; + status = smbcli_deltree(spdata->tree, dirname); + if (status <= 0) { + return NULL; + } + + Py_RETURN_NONE; +} + +/* * Check existence of a path */ static PyObject *py_smb_chkpath(pytalloc_Object *self, PyObject *args) @@ -526,6 +548,9 @@ static PyMethodDef py_smb_methods[] = { { "rmdir", (PyCFunction)py_smb_rmdir, METH_VARARGS, "rmdir(path) -> None\n\n \ Delete a directory." }, + { "deltree", (PyCFunction)py_smb_deltree, METH_VARARGS, + "deltree(path) -> None\n\n \ + Delete a directory and all its contents." }, { "chkpath", (PyCFunction)py_smb_chkpath, METH_VARARGS, "chkpath(path) -> True or False\n\n \ Return true if path exists, false otherwise." }, diff --git a/source4/scripting/python/samba/netcmd/gpo.py b/source4/scripting/python/samba/netcmd/gpo.py index 88c7622..d2d19e2 100644 --- a/source4/scripting/python/samba/netcmd/gpo.py +++ b/source4/scripting/python/samba/netcmd/gpo.py @@ -1,7 +1,7 @@ # implement samba_tool gpo commands # # Copyright Andrew Tridgell 2010 -# Copyright Amitay Isaacs 2011 <ami...@gmail.com> +# Copyright Amitay Isaacs 2011-2012 <ami...@gmail.com> # # based on C implementation by Guenther Deschner and Wilco Baan Hofman # @@ -121,7 +121,7 @@ def get_gpo_dn(samdb, gpo): '''Construct the DN for gpo''' dn = samdb.get_default_basedn() - dn.add_child(ldb.Dn(samdb, "CN=Policies,DC=System")) + dn.add_child(ldb.Dn(samdb, "CN=Policies,CN=System")) dn.add_child(ldb.Dn(samdb, "CN=%s" % gpo)) return dn @@ -165,6 +165,56 @@ def get_gpo_info(samdb, gpo=None, displayname=None, dn=None): return msg +def get_gpo_containers(samdb, gpo): + '''lists dn of containers for a GPO''' + + search_expr = "(&(objectClass=*)(gPLink=*%s*))" % gpo + try: + msg = samdb.search(expression=search_expr, attrs=['gPLink']) + except Exception, e: + raise CommandError("Could not find container(s) with GPO %s" % gpo, e) + + return msg + + +def del_gpo_link(samdb, container_dn, gpo): + '''delete GPO link for the container''' + # Check if valid Container DN and get existing GPlinks + try: + msg = samdb.search(base=container_dn, scope=ldb.SCOPE_BASE, + expression="(objectClass=*)", + attrs=['gPLink'])[0] + except Exception, e: + raise CommandError("Container '%s' does not exist" % container_dn, e) + + found = False + gpo_dn = str(get_gpo_dn(samdb, gpo)) + if 'gPLink' in msg: + gplist = parse_gplink(msg['gPLink'][0]) + for g in gplist: + if g['dn'].lower() == gpo_dn.lower(): + gplist.remove(g) + found = True + break + else: + raise CommandError("No GPO(s) linked to this container") + + if not found: + raise CommandError("GPO '%s' not linked to this container" % gpo) + + m = ldb.Message() + m.dn = container_dn + if gplist: + gplink_str = encode_gplink(gplist) + m['r0'] = ldb.MessageElement(gplink_str, ldb.FLAG_MOD_REPLACE, 'gPLink') + else: + m['d0'] = ldb.MessageElement(msg['gPLink'][0], ldb.FLAG_MOD_DELETE, 'gPLink') + try: + samdb.modify(m) + except Exception, e: + raise CommandError("Error removing GPO from container", e) + + def parse_unc(unc): '''Parse UNC string into a hostname, a service, and a filepath''' if unc.startswith('\\\\') and unc.startswith('//'): @@ -300,15 +350,15 @@ class cmd_list(Command): msg = self.samdb.search(expression='(&(|(samAccountName=%s)(samAccountName=%s$))(objectClass=User))' % (ldb.binary_encode(username),ldb.binary_encode(username))) user_dn = msg[0].dn - except Exception, e: - raise CommandError("Failed to find account %s" % username, e) + except Exception: + raise CommandError("Failed to find account %s" % username) # check if its a computer account try: msg = self.samdb.search(base=user_dn, scope=ldb.SCOPE_BASE, attrs=['objectClass'])[0] is_computer = 'computer' in msg['objectClass'] - except Exception, e: - raise CommandError("Failed to find objectClass for user %s" % username, e) + except Exception: + raise CommandError("Failed to find objectClass for user %s" % username) session_info_flags = ( AUTH_SESSION_INFO_DEFAULT_GROUPS | AUTH_SESSION_INFO_AUTHENTICATED ) @@ -412,8 +462,8 @@ class cmd_show(Command): try: msg = get_gpo_info(self.samdb, gpo)[0] - except Exception, e: - raise CommandError("GPO %s does not exist" % gpo, e) + except Exception: + raise CommandError("GPO '%s' does not exist" % gpo) secdesc_ndr = msg['ntSecurityDescriptor'][0] secdesc = ndr_unpack(security.descriptor, secdesc_ndr) @@ -458,11 +508,11 @@ class cmd_getlink(Command): try: msg = self.samdb.search(base=container_dn, scope=ldb.SCOPE_BASE, expression="(objectClass=*)", - attrs=['gPlink'])[0] - except Exception, e: - raise CommandError("Could not find Container DN %s (%s)" % container_dn, e) + attrs=['gPLink'])[0] + except Exception: + raise CommandError("Container '%s' does not exist" % container_dn) - if 'gPLink' in msg: + if msg['gPLink']: self.outf.write("GPO(s) linked to DN %s\n" % container_dn) gplist = parse_gplink(msg['gPLink'][0]) for g in gplist: @@ -515,17 +565,17 @@ class cmd_setlink(Command): # Check if valid GPO DN try: msg = get_gpo_info(self.samdb, gpo=gpo)[0] - except Exception, e: - raise CommandError("GPO %s does not exist" % gpo_dn, e) - gpo_dn = get_gpo_dn(self.samdb, gpo) + except Exception: + raise CommandError("GPO '%s' does not exist" % gpo) + gpo_dn = str(get_gpo_dn(self.samdb, gpo)) # Check if valid Container DN try: msg = self.samdb.search(base=container_dn, scope=ldb.SCOPE_BASE, expression="(objectClass=*)", - attrs=['gPlink'])[0] - except Exception, e: - raise CommandError("Could not find container DN %s" % container_dn, e) + attrs=['gPLink'])[0] + except Exception: + raise CommandError("Container '%s' does not exist" % container_dn) # Update existing GPlinks or Add new one existing_gplink = False @@ -538,7 +588,9 @@ class cmd_setlink(Command): g['options'] = gplink_options found = True break - if not found: + if found: + raise CommandError("GPO '%s' already linked to this container" % gpo) + else: gplist.insert(0, { 'dn' : gpo_dn, 'options' : gplink_options }) else: gplist = [] @@ -574,13 +626,13 @@ class cmd_dellink(Command): "credopts": options.CredentialsOptions, } - takes_args = ['container_dn', 'gpo'] + takes_args = ['container', 'gpo'] takes_options = [ Option("-H", help="LDB URL for database or target server", type=str), ] - def run(self, container_dn, gpo_dn, H=None, sambaopts=None, credopts=None, + def run(self, container, gpo, H=None, sambaopts=None, credopts=None, versionopts=None): self.lp = sambaopts.get_loadparm() @@ -592,44 +644,50 @@ class cmd_dellink(Command): # Check if valid GPO try: - msg = get_gpo_info(self.sambdb, gpo=gpo)[0] - except Exception, e: - raise CommandError("GPO %s does not exist" % gpo, e) - gpo_dn = get_gpo_dn(self.samdb, gpo) + get_gpo_info(self.samdb, gpo=gpo)[0] + except Exception: + raise CommandError("GPO '%s' does not exist" % gpo) - # Check if valid Container DN and get existing GPlinks - try: - msg = self.samdb.search(base=container_dn, scope=ldb.SCOPE_BASE, - expression="(objectClass=*)", - attrs=['gPlink'])[0] - except Exception, e: - raise CommandError("Could not find container DN %s" % dn, e) + container_dn = ldb.Dn(self.samdb, container) + del_gpo_link(self.samdb, container_dn, gpo) + self.outf.write("Deleted GPO link.\n") + cmd_getlink().run(container_dn, H, sambaopts, credopts, versionopts) - if 'gPLink' in msg: - gplist = parse_gplink(msg['gPLink'][0]) - for g in gplist: - if g['dn'].lower() == gpo_dn.lower(): - gplist.remove(g) - break - else: - raise CommandError("Specified GPO is not linked to this container") - m = ldb.Message() - m.dn = ldb.Dn(self.samdb, container_dn) +class cmd_listcontainers(Command): + """List all linked containers for a GPO""" - if gplist: - gplink_str = encode_gplink(gplist) - m['new_value'] = ldb.MessageElement(gplink_str, ldb.FLAG_MOD_REPLACE, 'gPLink') - else: - m['new_value'] = ldb.MessageElement('', ldb.FLAG_MOD_DELETE, 'gPLink') + synopsis = "%prog <gpo> [options]" - try: - self.samdb.modify(m) - except Exception, e: - raise CommandError("Error Removing GPO Link (%s)" % e) + takes_optiongroups = { + "sambaopts": options.SambaOptions, + "versionopts": options.VersionOptions, + "credopts": options.CredentialsOptions, + } - self.outf.write("Deleted GPO link.\n") - cmd_getlink().run(container_dn, H, sambaopts, credopts, versionopts) + takes_args = ['gpo'] + + takes_options = [ + Option("-H", help="LDB URL for database or target server", type=str) + ] + + def run(self, gpo, H=None, sambaopts=None, credopts=None, + versionopts=None): + + self.lp = sambaopts.get_loadparm() + self.creds = credopts.get_credentials(self.lp, fallback_machine=True) + + self.url = dc_url(self.lp, self.creds, H) + + samdb_connect(self) + + msg = get_gpo_containers(self.samdb, gpo) + if len(msg): + self.outf.write("Container(s) using GPO %s\n" % gpo) + for m in msg: + self.outf.write(" DN: %s\n" % m['dn']) + else: + self.outf.write("No Containers using GPO %s\n" % gpo) class cmd_getinheritance(Command): @@ -652,19 +710,19 @@ class cmd_getinheritance(Command): def run(self, container_dn, H=None, sambaopts=None, credopts=None, versionopts=None): - self.url = H self.lp = sambaopts.get_loadparm() - self.creds = credopts.get_credentials(self.lp, fallback_machine=True) + self.url = dc_url(self.lp, self.creds, H) + samdb_connect(self) try: msg = self.samdb.search(base=container_dn, scope=ldb.SCOPE_BASE, expression="(objectClass=*)", attrs=['gPOptions'])[0] - except Exception, e: - raise CommandError("Could not find Container DN %s" % container_dn, e) + except Exception: + raise CommandError("Container '%s' does not exist" % container_dn) inheritance = 0 if 'gPOptions' in msg: @@ -703,19 +761,18 @@ class cmd_setinheritance(Command): else: raise CommandError("Unknown inheritance state (%s)" % inherit_state) - self.url = H self.lp = sambaopts.get_loadparm() - self.creds = credopts.get_credentials(self.lp, fallback_machine=True) - samdb_connect(self) + self.url = dc_url(self.lp, self.creds, H) + samdb_connect(self) try: msg = self.samdb.search(base=container_dn, scope=ldb.SCOPE_BASE, expression="(objectClass=*)", attrs=['gPOptions'])[0] - except Exception, e: - raise CommandError("Could not find Container DN %s" % container_dn, e) + except Exception: + raise CommandError("Container '%s' does not exist" % container_dn) m = ldb.Message() m.dn = ldb.Dn(self.samdb, container_dn) @@ -754,14 +811,19 @@ class cmd_fetch(Command): self.lp = sambaopts.get_loadparm() self.creds = credopts.get_credentials(self.lp, fallback_machine=True) - dc_hostname = netcmd_finddc(self.lp, self.creds) - self.url = dc_url(self.lp, self.creds, H, dc=dc_hostname) + # We need to know writable DC to setup SMB connection + if H and H.startswith('ldap://'): + dc_hostname = H[7:] + self.url = H + else: + dc_hostname = netcmd_finddc(self.lp, self.creds) + self.url = dc_url(self.lp, self.creds, dc=dc_hostname) samdb_connect(self) try: msg = get_gpo_info(self.samdb, gpo)[0] - except Exception, e: - raise CommandError("GPO %s does not exist" % gpo) + except Exception: + raise CommandError("GPO '%s' does not exist" % gpo) # verify UNC path unc = msg['gPCFileSysPath'][0] @@ -773,8 +835,8 @@ class cmd_fetch(Command): # SMB connect to DC try: conn = smb.SMB(dc_hostname, service, lp=self.lp, creds=self.creds) - except Exception, e: - raise CommandError("Error connecting to '%s' using SMB" % dc_hostname, e) + except Exception: + raise CommandError("Error connecting to '%s' using SMB" % dc_hostname) # Copy GPT if tmpdir is None: @@ -823,9 +885,14 @@ class cmd_create(Command): self.lp = sambaopts.get_loadparm() self.creds = credopts.get_credentials(self.lp, fallback_machine=True) - self.url = dc_url(self.lp, self.creds, url=H) + # We need to know writable DC to setup SMB connection + if H and H.startswith('ldap://'): + dc_hostname = H[7:] + self.url = H + else: + dc_hostname = netcmd_finddc(self.lp, self.creds) + self.url = dc_url(self.lp, self.creds, dc=dc_hostname) - dc_hostname = netcmd_finddc(self.lp, self.creds) samdb_connect(self) msg = get_gpo_info(self.samdb, displayname=displayname) @@ -871,12 +938,10 @@ class cmd_create(Command): self.samdb.transaction_start() try: # Add cn=<guid> - gpo_dn = self.samdb.get_default_basedn() - gpo_dn.add_child(ldb.Dn(self.samdb, "CN=Policies,CN=System")) - gpo_dn.add_child(ldb.Dn(self.samdb, "CN=%s" % gpo)) + gpo_dn = get_gpo_dn(self.samdb, gpo) m = ldb.Message() - m.dn = ldb.Dn(self.samdb, gpo_dn.get_linearized()) + m.dn = gpo_dn m['a01'] = ldb.MessageElement("groupPolicyContainer", ldb.FLAG_MOD_ADD, "objectClass") m['a02'] = ldb.MessageElement(displayname, ldb.FLAG_MOD_ADD, "displayName") m['a03'] = ldb.MessageElement(unc_path, ldb.FLAG_MOD_ADD, "gPCFileSysPath") @@ -920,7 +985,7 @@ class cmd_create(Command): security.SECINFO_DACL | security.SECINFO_PROTECTED_DACL ) conn.set_acl(sharepath, fs_sd, sio) - except: + except Exception: self.samdb.transaction_cancel() raise else: @@ -929,6 +994,84 @@ class cmd_create(Command): self.outf.write("GPO '%s' created as %s\n" % (displayname, gpo)) +class cmd_del(Command): + """Delete GPO""" + + synopsis = "%prog <gpo> [options]" + + takes_optiongroups = { + "sambaopts": options.SambaOptions, + "versionopts": options.VersionOptions, + "credopts": options.CredentialsOptions, + } + + takes_args = ['gpo'] + + takes_options = [ + Option("-H", help="LDB URL for database or target server", type=str), + ] + + def run(self, gpo, H=None, sambaopts=None, credopts=None, + versionopts=None): + + self.lp = sambaopts.get_loadparm() + self.creds = credopts.get_credentials(self.lp, fallback_machine=True) + + # We need to know writable DC to setup SMB connection + if H and H.startswith('ldap://'): + dc_hostname = H[7:] + self.url = H + else: + dc_hostname = netcmd_finddc(self.lp, self.creds) + self.url = dc_url(self.lp, self.creds, dc=dc_hostname) + + samdb_connect(self) + + # Check if valid GPO + try: + get_gpo_info(self.samdb, gpo=gpo)[0] + except Exception: + raise CommandError("GPO '%s' does not exist" % gpo) + + realm = self.lp.get('realm') + unc_path = "\\\\%s\\sysvol\\%s\\Policies\\%s" % (realm, realm, gpo) + + # Connect to DC over SMB + [dom_name, service, sharepath] = parse_unc(unc_path) + try: + conn = smb.SMB(dc_hostname, service, lp=self.lp, creds=self.creds) + except Exception, e: + raise CommandError("Error connecting to '%s' using SMB" % dc_hostname, e) + + self.samdb.transaction_start() + try: + # Check for existing links + msg = get_gpo_containers(self.samdb, gpo) + + if len(msg): + self.outf.write("GPO %s is linked to containers\n" % gpo) + for m in msg: + del_gpo_link(self.samdb, m['dn'], gpo) + self.outf.write(" Removed link from %s.\n" % m['dn']) + + # Remove LDAP entries + gpo_dn = get_gpo_dn(self.samdb, gpo) + self.samdb.delete(ldb.Dn(self.samdb, "CN=User,%s" % str(gpo_dn))) + self.samdb.delete(ldb.Dn(self.samdb, "CN=Machine,%s" % str(gpo_dn))) + self.samdb.delete(gpo_dn) + + # Remove GPO files + conn.deltree(sharepath) + -- Samba Shared Repository