3 # implement samba_tool gpo commands
5 # Copyright Andrew Tridgell 2010
6 # Copyright Giampaolo Lauria 2011 <lauria2@yahoo.com>
7 # Copyright Amitay Isaacs 2011 <amitay@gmail.com>
9 # based on C implementation by Guenther Deschner and Wilco Baan Hofman
11 # This program is free software; you can redistribute it and/or modify
12 # it under the terms of the GNU General Public License as published by
13 # the Free Software Foundation; either version 3 of the License, or
14 # (at your option) any later version.
16 # This program is distributed in the hope that it will be useful,
17 # but WITHOUT ANY WARRANTY; without even the implied warranty of
18 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 # GNU General Public License for more details.
21 # You should have received a copy of the GNU General Public License
22 # along with this program. If not, see <http://www.gnu.org/licenses/>.
26 import samba.getopt as options
29 from samba.auth import system_session
30 from samba.netcmd import (
36 from samba.samdb import SamDB
37 from samba import drs_utils, nttime2string, dsdb, dcerpc
38 from samba.dcerpc import misc
39 from samba.ndr import ndr_unpack
42 from samba.auth import AUTH_SESSION_INFO_DEFAULT_GROUPS, AUTH_SESSION_INFO_AUTHENTICATED, AUTH_SESSION_INFO_SIMPLE_PRIVILEGES
43 from samba.netcmd.common import netcmd_finddc
44 from samba import policy
49 def samdb_connect(ctx):
50 '''make a ldap connection to the server'''
52 ctx.samdb = SamDB(url=ctx.url,
53 session_info=system_session(),
54 credentials=ctx.creds, lp=ctx.lp)
56 raise CommandError("LDAP connection to %s failed " % ctx.url, e)
59 def attr_default(msg, attrname, default):
60 '''get an attribute from a ldap msg with a default'''
62 return msg[attrname][0]
66 def gpo_flags_string(value):
67 '''return gpo flags string'''
68 flags = policy.get_gpo_flags(value)
76 def gplink_options_string(value):
77 '''return gplink options string'''
78 options = policy.get_gplink_options(value)
82 ret = ' '.join(options)
86 def parse_gplink(gplink):
87 '''parse a gPLink into an array of dn and options'''
94 if len(d) != 2 or not d[0].startswith("[LDAP://"):
95 raise RuntimeError("Badly formed gPLink '%s'" % g)
96 ret.append({ 'dn' : d[0][8:], 'options' : int(d[1])})
100 def encode_gplink(gplist):
101 '''Encode an array of dn and options into gPLink string'''
104 ret += "[LDAP://%s;%d]" % (g['dn'], g['options'])
108 def dc_url(lp, creds, url=None, dc=None):
109 '''If URL is not specified, return URL for writable DC.
110 If dc is provided, use that to construct ldap URL'''
115 dc = netcmd_finddc(lp, creds)
117 raise RunTimeError("Could not find a DC for domain", e)
122 def get_gpo_dn(samdb, gpo):
123 '''Construct the DN for gpo'''
125 dn = samdb.get_default_basedn()
126 dn.add_child(ldb.Dn(samdb, "CN=Policies,DC=System"))
127 dn.add_child(ldb.Dn(samdb, "CN=%s" % gpo))
131 def get_gpo_info(samdb, gpo=None, displayname=None, dn=None):
132 '''Get GPO information using gpo, displayname or dn'''
134 policies_dn = samdb.get_default_basedn()
135 policies_dn.add_child(ldb.Dn(samdb, "CN=Policies,CN=System"))
137 base_dn = policies_dn
138 search_expr = "(objectClass=groupPolicyContainer)"
139 search_scope = ldb.SCOPE_ONELEVEL
142 search_expr = "(&(objectClass=groupPolicyContainer)(name=%s))" % ldb.binary_encode(gpo)
144 if displayname is not None:
145 search_expr = "(&(objectClass=groupPolicyContainer)(displayname=%s))" % ldb.binary_encode(displayname)
149 search_scope = ldb.SCOPE_BASE
152 msg = samdb.search(base=base_dn, scope=search_scope,
153 expression=search_expr,
154 attrs=['nTSecurityDescriptor',
162 mesg = "Cannot get information for GPO %s" % gpo
164 mesg = "Cannot get information for GPOs"
165 raise CommandError(mesg, e)
171 '''Parse UNC string into a hostname, a service, and a filepath'''
172 if unc.startswith('\\\\') and unc.startswith('//'):
174 tmp = unc[2:].split('/', 2)
177 tmp = unc[2:].split('\\', 2)
183 def copy_directory_remote_to_local(conn, remotedir, localdir):
184 if not os.path.isdir(localdir):
186 r_dirs = [ remotedir ]
187 l_dirs = [ localdir ]
192 dirlist = conn.list(r_dir)
194 r_name = r_dir + '\\' + e['name']
195 l_name = os.path.join(l_dir, e['name'])
197 if e['attrib'] & smb.FILE_ATTRIBUTE_DIRECTORY:
198 r_dirs.append(r_name)
199 l_dirs.append(l_name)
202 data = conn.loadfile(r_name)
203 file(l_name, 'w').write(data)
206 def copy_directory_local_to_remote(conn, localdir, remotedir):
207 if not conn.chkpath(remotedir):
208 conn.mkdir(remotedir)
209 l_dirs = [ localdir ]
210 r_dirs = [ remotedir ]
215 dirlist = os.listdir(l_dir)
217 l_name = os.path.join(l_dir, e)
218 r_name = r_dir + '\\' + e
220 if os.path.isdir(l_name):
221 l_dirs.append(l_name)
222 r_dirs.append(r_name)
225 data = file(l_name, 'r').read()
226 conn.savefile(r_name, data)
229 def create_directory_hier(conn, remotedir):
230 elems = remotedir.replace('/', '\\').split('\\')
233 path = path + '\\' + e
234 if not conn.chkpath(path):
238 class cmd_listall(Command):
241 synopsis = "%prog gpo listall [options]"
244 Option("-H", "--URL", help="LDB URL for database or target server", type=str,
245 metavar="URL", dest="H")
248 def run(self, H=None, sambaopts=None, credopts=None, versionopts=None):
250 self.lp = sambaopts.get_loadparm()
251 self.creds = credopts.get_credentials(self.lp, fallback_machine=True)
253 self.url = dc_url(self.lp, self.creds, H)
257 msg = get_gpo_info(self.samdb, None)
260 print("GPO : %s" % m['name'][0])
261 print("display name : %s" % m['displayName'][0])
262 print("path : %s" % m['gPCFileSysPath'][0])
263 print("dn : %s" % m.dn)
264 print("version : %s" % attr_default(m, 'versionNumber', '0'))
265 print("flags : %s" % gpo_flags_string(int(attr_default(m, 'flags', 0))))
269 class cmd_list(Command):
270 """list GPOs for an account"""
272 synopsis = "%prog gpo list <username> [options]"
274 takes_args = [ 'username' ]
277 Option("-H", "--URL", help="LDB URL for database or target server", type=str,
278 metavar="URL", dest="H")
281 def run(self, username, H=None, sambaopts=None, credopts=None, versionopts=None):
283 self.lp = sambaopts.get_loadparm()
284 self.creds = credopts.get_credentials(self.lp, fallback_machine=True)
286 self.url = dc_url(self.lp, self.creds, H)
291 msg = self.samdb.search(expression='(&(|(samAccountName=%s)(samAccountName=%s$))(objectClass=User))' %
292 (ldb.binary_encode(username),ldb.binary_encode(username)))
295 raise CommandError("Failed to find account %s" % username, e)
297 # check if its a computer account
299 msg = self.samdb.search(base=user_dn, scope=ldb.SCOPE_BASE, attrs=['objectClass'])[0]
300 is_computer = 'computer' in msg['objectClass']
302 raise CommandError("Failed to find objectClass for user %s" % username, e)
304 session_info_flags = ( AUTH_SESSION_INFO_DEFAULT_GROUPS |
305 AUTH_SESSION_INFO_AUTHENTICATED )
307 # When connecting to a remote server, don't look up the local privilege DB
308 if self.url is not None and self.url.startswith('ldap'):
309 session_info_flags |= AUTH_SESSION_INFO_SIMPLE_PRIVILEGES
311 session = samba.auth.user_session(self.samdb, lp_ctx=self.lp, dn=user_dn,
312 session_info_flags=session_info_flags)
314 token = session.security_token
319 dn = ldb.Dn(self.samdb, str(user_dn)).parent()
321 msg = self.samdb.search(base=dn, scope=ldb.SCOPE_BASE, attrs=['gPLink', 'gPOptions'])[0]
323 glist = parse_gplink(msg['gPLink'][0])
325 if not inherit and not (g['options'] & dsdb.GPLINK_OPT_ENFORCE):
327 if g['options'] & dsdb.GPLINK_OPT_DISABLE:
331 gmsg = self.samdb.search(base=g['dn'], scope=ldb.SCOPE_BASE,
332 attrs=['name', 'displayName', 'flags',
333 'ntSecurityDescriptor'])
335 print("Failed to fetch gpo object %s" % g['dn'])
338 secdesc_ndr = gmsg[0]['ntSecurityDescriptor'][0]
339 secdesc = ndr_unpack(dcerpc.security.descriptor, secdesc_ndr)
342 samba.security.access_check(secdesc, token,
343 dcerpc.security.SEC_STD_READ_CONTROL |
344 dcerpc.security.SEC_ADS_LIST |
345 dcerpc.security.SEC_ADS_READ_PROP)
347 print("Failed access check on %s" % msg.dn)
350 # check the flags on the GPO
351 flags = int(attr_default(gmsg[0], 'flags', 0))
352 if is_computer and (flags & dsdb.GPO_FLAG_MACHINE_DISABLE):
354 if not is_computer and (flags & dsdb.GPO_FLAG_USER_DISABLE):
356 gpos.append((gmsg[0]['displayName'][0], gmsg[0]['name'][0]))
358 # check if this blocks inheritance
359 gpoptions = int(attr_default(msg, 'gPOptions', 0))
360 if gpoptions & dsdb.GPO_BLOCK_INHERITANCE:
363 if dn == self.samdb.get_default_basedn():
372 print("GPOs for %s %s" % (msg_str, username))
374 print(" %s %s" % (g[0], g[1]))
377 class cmd_show(Command):
378 """Show information for a GPO"""
380 synopsis = "%prog gpo show <gpo> [options]"
382 takes_optiongroups = {
383 "sambaopts": options.SambaOptions,
384 "versionopts": options.VersionOptions,
385 "credopts": options.CredentialsOptions,
388 takes_args = [ 'gpo' ]
391 Option("-H", help="LDB URL for database or target server", type=str)
394 def run(self, gpo, H=None, sambaopts=None, credopts=None, versionopts=None):
396 self.lp = sambaopts.get_loadparm()
397 self.creds = credopts.get_credentials(self.lp, fallback_machine=True)
399 self.url = dc_url(self.lp, self.creds, H)
404 msg = get_gpo_info(self.samdb, gpo)[0]
406 raise CommandError("GPO %s does not exist" % gpo, e)
408 secdesc_ndr = msg['ntSecurityDescriptor'][0]
409 secdesc = ndr_unpack(dcerpc.security.descriptor, secdesc_ndr)
411 print("GPO : %s" % msg['name'][0])
412 print("display name : %s" % msg['displayName'][0])
413 print("path : %s" % msg['gPCFileSysPath'][0])
414 print("dn : %s" % msg.dn)
415 print("version : %s" % attr_default(msg, 'versionNumber', '0'))
416 print("flags : %s" % gpo_flags_string(int(attr_default(msg, 'flags', 0))))
417 print("ACL : %s" % secdesc.as_sddl())
421 class cmd_getlink(Command):
422 """List GPO Links for a container"""
424 synopsis = "%prog gpo getlink <container_dn> [options]"
426 takes_optiongroups = {
427 "sambaopts": options.SambaOptions,
428 "versionopts": options.VersionOptions,
429 "credopts": options.CredentialsOptions,
432 takes_args = [ 'container_dn' ]
435 Option("-H", help="LDB URL for database or target server", type=str)
438 def run(self, container_dn, H=None, sambaopts=None, credopts=None,
441 self.lp = sambaopts.get_loadparm()
442 self.creds = credopts.get_credentials(self.lp, fallback_machine=True)
444 self.url = dc_url(self.lp, self.creds, H)
449 msg = self.samdb.search(base=container_dn, scope=ldb.SCOPE_BASE,
450 expression="(objectClass=*)",
453 raise CommandError("Could not find Container DN %s (%s)" % container_dn, e)
456 print("GPO(s) linked to DN %s" % container_dn)
457 gplist = parse_gplink(msg['gPLink'][0])
459 msg = get_gpo_info(self.samdb, dn=g['dn'])
460 print(" GPO : %s" % msg[0]['name'][0])
461 print(" Name : %s" % msg[0]['displayName'][0])
462 print(" Options : %s" % gplink_options_string(g['options']))
465 print("No GPO(s) linked to DN=%s" % container_dn)
468 class cmd_setlink(Command):
469 """Add or Update a GPO link to a container"""
471 synopsis = "%prog gpo setlink <container_dn> <gpo> [options]"
473 takes_optiongroups = {
474 "sambaopts": options.SambaOptions,
475 "versionopts": options.VersionOptions,
476 "credopts": options.CredentialsOptions,
479 takes_args = [ 'container_dn', 'gpo' ]
482 Option("-H", help="LDB URL for database or target server", type=str),
483 Option("--disable", dest="disabled", default=False, action='store_true',
484 help="Disable policy"),
485 Option("--enforce", dest="enforced", default=False, action='store_true',
486 help="Enforce policy")
489 def run(self, container_dn, gpo, H=None, disabled=False, enforced=False,
490 sambaopts=None, credopts=None, versionopts=None):
492 self.lp = sambaopts.get_loadparm()
493 self.creds = credopts.get_credentials(self.lp, fallback_machine=True)
495 self.url = dc_url(self.lp, self.creds, H)
501 gplink_options |= dsdb.GPLINK_OPT_DISABLE
503 gplink_options |= dsdb.GPLINK_OPT_ENFORCE
505 # Check if valid GPO DN
507 msg = get_gpo_info(self.samdb, gpo=gpo)[0]
509 raise CommandError("GPO %s does not exist" % gpo_dn, e)
510 gpo_dn = get_gpo_dn(self.samdb, gpo)
512 # Check if valid Container DN
514 msg = self.samdb.search(base=container_dn, scope=ldb.SCOPE_BASE,
515 expression="(objectClass=*)",
518 raise CommandError("Could not find container DN %s" % container_dn, e)
520 # Update existing GPlinks or Add new one
521 existing_gplink = False
523 gplist = parse_gplink(msg['gPLink'][0])
524 existing_gplink = True
527 if g['dn'].lower() == gpo_dn.lower():
528 g['options'] = gplink_options
532 gplist.insert(0, { 'dn' : gpo_dn, 'options' : gplink_options })
535 gplist.append({ 'dn' : gpo_dn, 'options' : gplink_options })
537 gplink_str = encode_gplink(gplist)
540 m.dn = ldb.Dn(self.samdb, container_dn)
543 m['new_value'] = ldb.MessageElement(gplink_str, ldb.FLAG_MOD_REPLACE, 'gPLink')
545 m['new_value'] = ldb.MessageElement(gplink_str, ldb.FLAG_MOD_ADD, 'gPLink')
550 raise CommandError("Error adding GPO Link", e)
552 print("Added/Updated GPO link")
553 cmd_getlink().run(container_dn, H, sambaopts, credopts, versionopts)
556 class cmd_dellink(Command):
557 """Delete GPO link from a container"""
559 synopsis = "%prog gpo dellink <container_dn> <gpo> [options]"
561 takes_optiongroups = {
562 "sambaopts": options.SambaOptions,
563 "versionopts": options.VersionOptions,
564 "credopts": options.CredentialsOptions,
567 takes_args = [ 'container_dn', 'gpo' ]
570 Option("-H", help="LDB URL for database or target server", type=str),
573 def run(self, container_dn, gpo_dn, H=None, sambaopts=None, credopts=None,
576 self.lp = sambaopts.get_loadparm()
577 self.creds = credopts.get_credentials(self.lp, fallback_machine=True)
579 self.url = dc_url(self.lp, self.creds, H)
585 msg = get_gpo_info(self.sambdb, gpo=gpo)[0]
587 raise CommandError("GPO %s does not exist" % gpo, e)
588 gpo_dn = get_gpo_dn(self.samdb, gpo)
590 # Check if valid Container DN and get existing GPlinks
592 msg = self.samdb.search(base=container_dn, scope=ldb.SCOPE_BASE,
593 expression="(objectClass=*)",
596 raise CommandError("Could not find container DN %s" % dn, e)
599 gplist = parse_gplink(msg['gPLink'][0])
601 if g['dn'].lower() == gpo_dn.lower():
605 raise CommandError("Specified GPO is not linked to this container");
608 m.dn = ldb.Dn(self.samdb, container_dn)
611 gplink_str = encode_gplink(gplist)
612 m['new_value'] = ldb.MessageElement(gplink_str, ldb.FLAG_MOD_REPLACE, 'gPLink')
614 m['new_value'] = ldb.MessageElement('', ldb.FLAG_MOD_DELETE, 'gPLink')
619 raise CommandError("Error Removing GPO Link (%s)" % e)
621 print("Deleted GPO link.")
622 cmd_getlink().run(container_dn, H, sambaopts, credopts, versionopts)
625 class cmd_getinheritance(Command):
626 """Get inheritance flag for a container"""
628 synopsis = "%prog gpo getinheritance <container_dn> [options]"
630 takes_optiongroups = {
631 "sambaopts": options.SambaOptions,
632 "versionopts": options.VersionOptions,
633 "credopts": options.CredentialsOptions,
636 takes_args = [ 'container_dn' ]
639 Option("-H", help="LDB URL for database or target server", type=str)
642 def run(self, container_dn, H=None, sambaopts=None, credopts=None,
646 self.lp = sambaopts.get_loadparm()
648 self.creds = credopts.get_credentials(self.lp, fallback_machine=True)
653 msg = self.samdb.search(base=container_dn, scope=ldb.SCOPE_BASE,
654 expression="(objectClass=*)",
655 attrs=['gPOptions'])[0]
657 raise CommandError("Could not find Container DN %s" % container_dn, e)
660 if 'gPOptions' in msg:
661 inheritance = int(msg['gPOptions'][0]);
663 if inheritance == dsdb.GPO_BLOCK_INHERITANCE:
664 print("Container has GPO_BLOCK_INHERITANCE")
666 print("Container has GPO_INHERIT")
669 class cmd_setinheritance(Command):
670 """Set inheritance flag on a container"""
672 synopsis = "%prog gpo setinheritance <container_dn> <block|inherit> [options]"
674 takes_optiongroups = {
675 "sambaopts": options.SambaOptions,
676 "versionopts": options.VersionOptions,
677 "credopts": options.CredentialsOptions,
680 takes_args = [ 'container_dn', 'inherit_state' ]
683 Option("-H", help="LDB URL for database or target server", type=str)
686 def run(self, container_dn, inherit_state, H=None, sambaopts=None, credopts=None,
689 if inherit_state.lower() == 'block':
690 inheritance = dsdb.GPO_BLOCK_INHERITANCE
691 elif inherit_state.lower() == 'inherit':
692 inheritance = dsdb.GPO_INHERIT
694 raise CommandError("Unknown inheritance state (%s)" % inherit_state)
697 self.lp = sambaopts.get_loadparm()
699 self.creds = credopts.get_credentials(self.lp, fallback_machine=True)
704 msg = self.samdb.search(base=container_dn, scope=ldb.SCOPE_BASE,
705 expression="(objectClass=*)",
706 attrs=['gPOptions'])[0]
708 raise CommandError("Could not find Container DN %s" % container_dn, e)
711 m.dn = ldb.Dn(self.samdb, container_dn)
713 if 'gPOptions' in msg:
714 m['new_value'] = ldb.MessageElement(str(inheritance), ldb.FLAG_MOD_REPLACE, 'gPOptions')
716 m['new_value'] = ldb.MessageElement(str(inheritance), ldb.FLAG_MOD_ADD, 'gPOptions');
721 raise CommandError("Error setting inheritance state %s" % inherit_state, e)
724 class cmd_fetch(Command):
727 synopsis = "%prog gpo fetch <gpo> [options]"
729 takes_optiongroups = {
730 "sambaopts": options.SambaOptions,
731 "versionopts": options.VersionOptions,
732 "credopts": options.CredentialsOptions,
735 takes_args = [ 'gpo' ]
738 Option("-H", help="LDB URL for database or target server", type=str),
739 Option("--tmpdir", help="Temporary directory for copying policy files", type=str)
742 def run(self, gpo, H=None, tmpdir=None, sambaopts=None, credopts=None, versionopts=None):
744 self.lp = sambaopts.get_loadparm()
745 self.creds = credopts.get_credentials(self.lp, fallback_machine=True)
747 dc_hostname = netcmd_finddc(self.lp, self.creds)
748 self.url = dc_url(self.lp, self.creds, H, dc=dc_hostname)
752 msg = get_gpo_info(self.samdb, gpo)[0]
754 raise CommandError("GPO %s does not exist" % gpo)
757 unc = msg['gPCFileSysPath'][0]
759 [dom_name, service, sharepath] = parse_unc(unc)
761 raise CommandError("Invalid GPO path (%s)" % unc)
765 conn = smb.SMB(dc_hostname, service, lp=self.lp, creds=self.creds)
767 raise CommandError("Error connecting to '%s' using SMB" % dc_hostname, e)
772 if not os.path.isdir(tmpdir):
773 raise CommandError("Temoprary directory '%s' does not exist" % tmpdir)
775 localdir = os.path.join(tmpdir, "policy")
776 if not os.path.isdir(localdir):
779 gpodir = os.path.join(localdir, gpo)
780 if os.path.isdir(gpodir):
781 raise CommandError("GPO directory '%s' already exists, refusing to overwrite" % gpodir)
785 copy_directory_remote_to_local(conn, sharepath, gpodir)
787 raise CommandError("Error copying GPO from DC", e)
788 print('GPO copied to %s' % gpodir)
791 class cmd_create(Command):
792 """Create an empty GPO"""
794 synopsis = "%prog gpo create <displayname> [options]"
796 takes_optiongroups = {
797 "sambaopts": options.SambaOptions,
798 "versionopts": options.VersionOptions,
799 "credopts": options.CredentialsOptions,
802 takes_args = [ 'displayname' ]
805 Option("-H", help="LDB URL for database or target server", type=str),
806 Option("--tmpdir", help="Temporary directory for copying policy files", type=str)
809 def run(self, displayname, H=None, tmpdir=None, sambaopts=None, credopts=None,
812 self.lp = sambaopts.get_loadparm()
813 self.creds = credopts.get_credentials(self.lp, fallback_machine=True)
815 self.url = dc_url(self.lp, self.creds, H)
817 dc_hostname = netcmd_finddc(self.lp, self.creds)
820 msg = get_gpo_info(self.samdb, displayname=displayname)
822 raise CommandError("A GPO already existing with name '%s'" % displayname)
825 guid = str(uuid.uuid4())
826 gpo = "{%s}" % guid.upper()
827 realm = self.lp.get('realm')
828 unc_path = "\\\\%s\\sysvol\\%s\\Policies\\%s" % (realm, realm, gpo)
833 if not os.path.isdir(tmpdir):
834 raise CommandError("Temporary directory '%s' does not exist" % tmpdir)
836 localdir = os.path.join(tmpdir, "policy")
837 if not os.path.isdir(localdir):
840 gpodir = os.path.join(localdir, gpo)
841 if os.path.isdir(gpodir):
842 raise CommandError("GPO directory '%s' already exists, refusing to overwrite" % gpodir)
846 os.mkdir(os.path.join(gpodir, "Machine"))
847 os.mkdir(os.path.join(gpodir, "User"))
848 gpt_contents = "[General]\r\nVersion=0\r\n"
849 file(os.path.join(gpodir, "GPT.INI"), "w").write(gpt_contents)
851 raise CommandError("Error Creating GPO files", e)
854 gpo_dn = self.samdb.get_default_basedn()
855 gpo_dn.add_child(ldb.Dn(self.samdb, "CN=Policies,CN=System"))
856 gpo_dn.add_child(ldb.Dn(self.samdb, "CN=%s" % gpo))
859 m.dn = ldb.Dn(self.samdb, gpo_dn.get_linearized())
860 m['a01'] = ldb.MessageElement("groupPolicyContainer", ldb.FLAG_MOD_ADD, "objectClass")
861 m['a02'] = ldb.MessageElement(displayname, ldb.FLAG_MOD_ADD, "displayName")
862 m['a03'] = ldb.MessageElement(unc_path, ldb.FLAG_MOD_ADD, "gPCFileSysPath")
863 m['a04'] = ldb.MessageElement("0", ldb.FLAG_MOD_ADD, "flags")
864 m['a05'] = ldb.MessageElement("0", ldb.FLAG_MOD_ADD, "versionNumber")
865 m['a06'] = ldb.MessageElement("TRUE", ldb.FLAG_MOD_ADD, "showInAdvancedViewOnly")
866 m['a07'] = ldb.MessageElement("2", ldb.FLAG_MOD_ADD, "gpcFunctionalityVersion")
870 raise CommandError("Error adding GPO in AD", e)
872 # Add cn=User,cn=<guid>
874 child_dn.add_child(ldb.Dn(self.samdb, "CN=User"))
877 m.dn = ldb.Dn(self.samdb, child_dn.get_linearized())
878 m['a01'] = ldb.MessageElement("container", ldb.FLAG_MOD_ADD, "objectClass")
879 m['a02'] = ldb.MessageElement("TRUE", ldb.FLAG_MOD_ADD, "showInAdvancedViewOnly")
883 raise CommandError("Error adding GPO in AD", e)
885 # Add cn=User,cn=<guid>
887 child_dn.add_child(ldb.Dn(self.samdb, "CN=Machine"))
890 m.dn = ldb.Dn(self.samdb, child_dn.get_linearized())
891 m['a01'] = ldb.MessageElement("container", ldb.FLAG_MOD_ADD, "objectClass")
892 m['a02'] = ldb.MessageElement("TRUE", ldb.FLAG_MOD_ADD, "showInAdvancedViewOnly")
896 raise CommandError("Error adding GPO in AD", e)
898 # Copy GPO files over SMB
899 [dom_name, service, sharepath] = parse_unc(unc_path)
901 conn = smb.SMB(dc_hostname, service, lp=self.lp, creds=self.creds)
903 raise CommandError("Error connecting to '%s' using SMB" % dc_hostname, e)
906 create_directory_hier(conn, sharepath)
907 copy_directory_local_to_remote(conn, gpodir, sharepath)
909 raise CommandError("Error Copying GPO to DC", e)
911 # Get new security descriptor
912 msg = get_gpo_info(self.samdb, gpo=gpo)[0]
913 ds_sd_ndr = msg['ntSecurityDescriptor'][0]
914 ds_sd = ndr_unpack(dcerpc.security.descriptor, ds_sd_ndr)
916 # Create a file system security descriptor
917 fs_sd = dcerpc.security.descriptor()
918 fs_sd.owner_sid = ds_sd.owner_sid
919 fs_sd.group_sid = ds_sd.group_sid
920 fs_sd.type = ds_sd.type
921 fs_sd.revision = ds_sd.revision
924 fs_sd.sacl = ds_sd.sacl
928 for ace in dacl.aces:
929 # Don't add the allow for SID_BUILTIN_PREW2K
930 if (not (ace.type & dcerpc.security.SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT) and
931 ace.trustee == dcerpc.security.SID_BUILTIN_PREW2K):
934 # Copy the ace from the directory server security descriptor
937 # Set specific inheritance flags for within the GPO
938 new_ace.flags |= (dcerpc.security.SEC_ACE_FLAG_OBJECT_INHERIT |
939 dcerpc.security.SEC_ACE_FLAG_CONTAINER_INHERIT)
940 if ace.trustee == dcerpc.security.SID_CREATOR_OWNER:
941 new_ace.flags |= dcerpc.security.SEC_ACE_FLAG_INHERIT_ONLY
943 # Get a directory access mask from the assigned access mask on the ldap object
944 new_ace.access_mask = policy.ads_to_dir_access_mask(ace.access_mask)
946 # Add the ace to DACL
947 fs_sd.dacl_add(new_ace)
951 conn.set_acl(sharepath, fs_sd)
953 raise CommandError("Error setting ACL on GPT", e)
955 print "GPO '%s' created as %s" % (displayname, gpo)
958 class cmd_setacl(Command):
959 """Set ACL on a GPO"""
962 class cmd_gpo(SuperCommand):
963 """Group Policy Object (GPO) commands"""
966 subcommands["listall"] = cmd_listall()
967 subcommands["list"] = cmd_list()
968 subcommands["show"] = cmd_show()
969 subcommands["getlink"] = cmd_getlink()
970 subcommands["setlink"] = cmd_setlink()
971 subcommands["dellink"] = cmd_dellink()
972 subcommands["getinheritance"] = cmd_getinheritance()
973 subcommands["setinheritance"] = cmd_setinheritance()
974 subcommands["fetch"] = cmd_fetch()
975 subcommands["create"] = cmd_create()
976 subcommands["setacl"] = cmd_setacl()