summaryrefslogtreecommitdiff
path: root/source4/scripting/python
diff options
context:
space:
mode:
authorIvo De Decker <ivo.dedecker@ugent.be>2013-05-10 13:34:01 +0200
committerIvo De Decker <ivo.dedecker@ugent.be>2013-05-10 13:34:01 +0200
commit1230d750f743f04cf199ee165072497f3abcd31f (patch)
tree491bc9f50143b0129490c1745f0002632ced64a2 /source4/scripting/python
parent31202ad025bcdeb2585d18dc3f4641b5cf9c0ec4 (diff)
downloadsamba-1230d750f743f04cf199ee165072497f3abcd31f.tar.gz
Imported Upstream version 4.0.3+dfsg1upstream/4.0.3+dfsg1
Diffstat (limited to 'source4/scripting/python')
-rw-r--r--source4/scripting/python/samba/dbchecker.py195
-rw-r--r--source4/scripting/python/samba/drs_utils.py2
-rw-r--r--source4/scripting/python/samba/netcmd/user.py6
-rw-r--r--source4/scripting/python/samba/provision/__init__.py92
-rw-r--r--source4/scripting/python/samba/provision/descriptor.py118
-rw-r--r--source4/scripting/python/samba/provision/sambadns.py30
-rw-r--r--source4/scripting/python/samba/samdb.py3
-rw-r--r--source4/scripting/python/samba/schema.py2
-rw-r--r--source4/scripting/python/samba/upgradehelpers.py3
9 files changed, 394 insertions, 57 deletions
diff --git a/source4/scripting/python/samba/dbchecker.py b/source4/scripting/python/samba/dbchecker.py
index e1be6c4faa..0bda0c22ac 100644
--- a/source4/scripting/python/samba/dbchecker.py
+++ b/source4/scripting/python/samba/dbchecker.py
@@ -21,9 +21,10 @@ import ldb
from samba import dsdb
from samba import common
from samba.dcerpc import misc
-from samba.ndr import ndr_unpack
+from samba.ndr import ndr_unpack, ndr_pack
from samba.dcerpc import drsblobs
from samba.common import dsdb_Dn
+from samba.dcerpc import security
class dbcheck(object):
@@ -49,6 +50,7 @@ class dbcheck(object):
self.fix_all_missing_backlinks = False
self.fix_all_orphaned_backlinks = False
self.fix_rmd_flags = False
+ self.fix_ntsecuritydescriptor = False
self.seize_fsmo_role = False
self.move_to_lost_and_found = False
self.fix_instancetype = False
@@ -58,12 +60,21 @@ class dbcheck(object):
self.schema_dn = samdb.get_schema_basedn()
self.rid_dn = ldb.Dn(samdb, "CN=RID Manager$,CN=System," + samdb.domain_dn())
self.ntds_dsa = samdb.get_dsServiceName()
+ self.class_schemaIDGUID = {}
- res = self.samdb.search(base=self.ntds_dsa, scope=ldb.SCOPE_BASE, attrs=['msDS-hasMasterNCs'])
+ res = self.samdb.search(base=self.ntds_dsa, scope=ldb.SCOPE_BASE, attrs=['msDS-hasMasterNCs', 'hasMasterNCs'])
if "msDS-hasMasterNCs" in res[0]:
self.write_ncs = res[0]["msDS-hasMasterNCs"]
else:
- self.write_ncs = None
+ # If the Forest Level is less than 2003 then there is no
+ # msDS-hasMasterNCs, so we fall back to hasMasterNCs
+ # no need to merge as all the NCs that are in hasMasterNCs must
+ # also be in msDS-hasMasterNCs (but not the opposite)
+ if "hasMasterNCs" in res[0]:
+ self.write_ncs = res[0]["hasMasterNCs"]
+ else:
+ self.write_ncs = None
+
def check_database(self, DN=None, scope=ldb.SCOPE_SUBTREE, controls=[], attrs=['*']):
'''perform a database check, returning the number of errors found'''
@@ -540,6 +551,164 @@ newSuperior: %s""" % (str(from_dn), str(to_rdn), str(to_base)))
"Failed to fix metadata for attribute %s" % attr):
self.report("Fixed metadata for attribute %s" % attr)
+ def ace_get_effective_inherited_type(self, ace):
+ if ace.flags & security.SEC_ACE_FLAG_INHERIT_ONLY:
+ return None
+
+ check = False
+ if ace.type == security.SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT:
+ check = True
+ elif ace.type == security.SEC_ACE_TYPE_ACCESS_DENIED_OBJECT:
+ check = True
+ elif ace.type == security.SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT:
+ check = True
+ elif ace.type == security.SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT:
+ check = True
+
+ if not check:
+ return None
+
+ if not ace.object.flags & security.SEC_ACE_INHERITED_OBJECT_TYPE_PRESENT:
+ return None
+
+ return str(ace.object.inherited_type)
+
+ def lookup_class_schemaIDGUID(self, cls):
+ if cls in self.class_schemaIDGUID:
+ return self.class_schemaIDGUID[cls]
+
+ flt = "(&(ldapDisplayName=%s)(objectClass=classSchema))" % cls
+ res = self.samdb.search(base=self.schema_dn,
+ expression=flt,
+ attrs=["schemaIDGUID"])
+ t = str(ndr_unpack(misc.GUID, res[0]["schemaIDGUID"][0]))
+
+ self.class_schemaIDGUID[cls] = t
+ return t
+
+ def process_sd(self, dn, obj):
+ sd_attr = "nTSecurityDescriptor"
+ sd_val = obj[sd_attr]
+
+ sd = ndr_unpack(security.descriptor, str(sd_val))
+
+ is_deleted = 'isDeleted' in obj and obj['isDeleted'][0].upper() == 'TRUE'
+ if is_deleted:
+ # we don't fix deleted objects
+ return (sd, None)
+
+ sd_clean = security.descriptor()
+ sd_clean.owner_sid = sd.owner_sid
+ sd_clean.group_sid = sd.group_sid
+ sd_clean.type = sd.type
+ sd_clean.revision = sd.revision
+
+ broken = False
+ last_inherited_type = None
+
+ aces = []
+ if sd.sacl is not None:
+ aces = sd.sacl.aces
+ for i in range(0, len(aces)):
+ ace = aces[i]
+
+ if not ace.flags & security.SEC_ACE_FLAG_INHERITED_ACE:
+ sd_clean.sacl_add(ace)
+ continue
+
+ t = self.ace_get_effective_inherited_type(ace)
+ if t is None:
+ continue
+
+ if last_inherited_type is not None:
+ if t != last_inherited_type:
+ # if it inherited from more than
+ # one type it's very likely to be broken
+ #
+ # If not the recalculation will calculate
+ # the same result.
+ broken = True
+ continue
+
+ last_inherited_type = t
+
+ aces = []
+ if sd.dacl is not None:
+ aces = sd.dacl.aces
+ for i in range(0, len(aces)):
+ ace = aces[i]
+
+ if not ace.flags & security.SEC_ACE_FLAG_INHERITED_ACE:
+ sd_clean.dacl_add(ace)
+ continue
+
+ t = self.ace_get_effective_inherited_type(ace)
+ if t is None:
+ continue
+
+ if last_inherited_type is not None:
+ if t != last_inherited_type:
+ # if it inherited from more than
+ # one type it's very likely to be broken
+ #
+ # If not the recalculation will calculate
+ # the same result.
+ broken = True
+ continue
+
+ last_inherited_type = t
+
+ if broken:
+ return (sd_clean, sd)
+
+ if last_inherited_type is None:
+ # ok
+ return (sd, None)
+
+ cls = None
+ try:
+ cls = obj["objectClass"][-1]
+ except KeyError, e:
+ pass
+
+ if cls is None:
+ res = self.samdb.search(base=dn, scope=ldb.SCOPE_BASE,
+ attrs=["isDeleted", "objectClass"],
+ controls=["show_recycled:1"])
+ o = res[0]
+ is_deleted = 'isDeleted' in o and o['isDeleted'][0].upper() == 'TRUE'
+ if is_deleted:
+ # we don't fix deleted objects
+ return (sd, None)
+ cls = o["objectClass"][-1]
+
+ t = self.lookup_class_schemaIDGUID(cls)
+
+ if t != last_inherited_type:
+ # broken
+ return (sd_clean, sd)
+
+ # ok
+ return (sd, None)
+
+ def err_wrong_sd(self, dn, sd, sd_broken):
+ '''re-write replPropertyMetaData elements for a single attribute for a
+ object. This is used to fix missing replPropertyMetaData elements'''
+ sd_attr = "nTSecurityDescriptor"
+ sd_val = ndr_pack(sd)
+ sd_flags = security.SECINFO_DACL | security.SECINFO_SACL
+
+ if not self.confirm_all('Fix %s on %s?' % (sd_attr, dn), 'fix_ntsecuritydescriptor'):
+ self.report('Not fixing %s on %s\n' % (sd_attr, dn))
+ return
+
+ nmsg = ldb.Message()
+ nmsg.dn = dn
+ nmsg[sd_attr] = ldb.MessageElement(sd_val, ldb.FLAG_MOD_REPLACE, sd_attr)
+ if self.do_modify(nmsg, ["sd_flags:1:%d" % sd_flags],
+ "Failed to fix metadata for attribute %s" % sd_attr):
+ self.report("Fixed attribute '%s' of '%s'\n" % (sd_attr, dn))
+
def is_fsmo_role(self, dn):
if dn == self.samdb.domain_dn:
return True
@@ -580,8 +749,19 @@ newSuperior: %s""" % (str(from_dn), str(to_rdn), str(to_base)))
attrs.append("replPropertyMetaData")
try:
+ sd_flags = 0
+ sd_flags |= security.SECINFO_OWNER
+ sd_flags |= security.SECINFO_GROUP
+ sd_flags |= security.SECINFO_DACL
+ sd_flags |= security.SECINFO_SACL
+
res = self.samdb.search(base=dn, scope=ldb.SCOPE_BASE,
- controls=["extended_dn:1:1", "show_recycled:1", "show_deleted:1"],
+ controls=[
+ "extended_dn:1:1",
+ "show_recycled:1",
+ "show_deleted:1",
+ "sd_flags:1:%d" % sd_flags,
+ ],
attrs=attrs)
except ldb.LdbError, (enum, estr):
if enum == ldb.ERR_NO_SUCH_OBJECT:
@@ -608,6 +788,13 @@ newSuperior: %s""" % (str(from_dn), str(to_rdn), str(to_base)))
got_repl_property_meta_data = True
continue
+ if str(attrname).lower() == 'ntsecuritydescriptor':
+ (sd, sd_broken) = self.process_sd(dn, obj)
+ if sd_broken is not None:
+ self.err_wrong_sd(dn, sd, sd_broken)
+ error_count += 1
+ continue
+
if str(attrname).lower() == 'objectclass':
normalised = self.samdb.dsdb_normalise_attributes(self.samdb_schema, attrname, list(obj[attrname]))
if list(normalised) != list(obj[attrname]):
diff --git a/source4/scripting/python/samba/drs_utils.py b/source4/scripting/python/samba/drs_utils.py
index 481eec2920..6e2cfea9ab 100644
--- a/source4/scripting/python/samba/drs_utils.py
+++ b/source4/scripting/python/samba/drs_utils.py
@@ -252,4 +252,4 @@ class drs_Replicate(object):
schema=schema, req_level=req_level, req=req)
if ctr.more_data == 0:
break
- req.highwatermark.tmp_highest_usn = ctr.new_highwatermark.tmp_highest_usn
+ req.highwatermark = ctr.new_highwatermark
diff --git a/source4/scripting/python/samba/netcmd/user.py b/source4/scripting/python/samba/netcmd/user.py
index dc50d7779c..7d045a8fdf 100644
--- a/source4/scripting/python/samba/netcmd/user.py
+++ b/source4/scripting/python/samba/netcmd/user.py
@@ -480,17 +480,17 @@ It is good security practice for the administrator to use the --must-change-at-n
The command may be run from the root userid or another authorized userid. The -H or --URL= option can be used to execute the command against a remote server.
Example1:
-samba-tool user setpassword TestUser1 passw0rd --URL=ldap://samba.samdom.example.com -Uadministrator%passw1rd
+samba-tool user setpassword TestUser1 --newpassword=passw0rd --URL=ldap://samba.samdom.example.com -Uadministrator%passw1rd
Example1 shows how to set the password of user TestUser1 on a remote LDAP server. The --URL parameter is used to specify the remote target server. The -U option is used to pass the username and password of a user that exists on the remote server and is authorized to update the server.
Example2:
-sudo samba-tool user setpassword TestUser2 passw0rd --must-change-at-next-login
+sudo samba-tool user setpassword TestUser2 --newpassword=passw0rd --must-change-at-next-login
Example2 shows how an administrator would reset the TestUser2 user's password to passw0rd. The user is running under the root userid using the sudo command. In this example the user TestUser2 must change their password the next time they logon to the account.
Example3:
-samba-tool user setpassword --filter=samaccountname=TestUser3 --password=passw0rd
+samba-tool user setpassword --filter=samaccountname=TestUser3 --newpassword=passw0rd
Example3 shows how an administrator would reset TestUser3 user's password to passw0rd using the --filter= option to specify the username.
diff --git a/source4/scripting/python/samba/provision/__init__.py b/source4/scripting/python/samba/provision/__init__.py
index e6ea855b57..a5385e7eb6 100644
--- a/source4/scripting/python/samba/provision/__init__.py
+++ b/source4/scripting/python/samba/provision/__init__.py
@@ -81,12 +81,21 @@ from samba.provision.descriptor import (
get_config_descriptor,
get_config_partitions_descriptor,
get_config_sites_descriptor,
+ get_config_ntds_quotas_descriptor,
+ get_config_delete_protected1_descriptor,
+ get_config_delete_protected1wd_descriptor,
+ get_config_delete_protected2_descriptor,
get_domain_descriptor,
get_domain_infrastructure_descriptor,
get_domain_builtin_descriptor,
get_domain_computers_descriptor,
get_domain_users_descriptor,
- get_domain_controllers_descriptor
+ get_domain_controllers_descriptor,
+ get_domain_delete_protected1_descriptor,
+ get_domain_delete_protected2_descriptor,
+ get_dns_partition_descriptor,
+ get_dns_forest_microsoft_dns_descriptor,
+ get_dns_domain_microsoft_dns_descriptor,
)
from samba.provision.common import (
setup_path,
@@ -94,6 +103,7 @@ from samba.provision.common import (
setup_modify_ldif,
)
from samba.provision.sambadns import (
+ get_dnsadmins_sid,
setup_ad_dns,
create_dns_update_list
)
@@ -135,10 +145,13 @@ class ProvisionPaths(object):
class ProvisionNames(object):
def __init__(self):
+ self.ncs = None
self.rootdn = None
self.domaindn = None
self.configdn = None
self.schemadn = None
+ self.dnsforestdn = None
+ self.dnsdomaindn = None
self.ldapmanagerdn = None
self.dnsdomain = None
self.realm = None
@@ -147,6 +160,7 @@ class ProvisionNames(object):
self.hostname = None
self.sitename = None
self.smbconf = None
+ self.name_map = {}
def find_provision_key_parameters(samdb, secretsdb, idmapdb, paths, smbconf,
@@ -184,7 +198,8 @@ def find_provision_key_parameters(samdb, secretsdb, idmapdb, paths, smbconf,
current = samdb.search(expression="(objectClass=*)",
base="", scope=ldb.SCOPE_BASE,
attrs=["defaultNamingContext", "schemaNamingContext",
- "configurationNamingContext","rootDomainNamingContext"])
+ "configurationNamingContext","rootDomainNamingContext",
+ "namingContexts"])
names.configdn = current[0]["configurationNamingContext"]
configdn = str(names.configdn)
@@ -198,6 +213,23 @@ def find_provision_key_parameters(samdb, secretsdb, idmapdb, paths, smbconf,
names.domaindn=current[0]["defaultNamingContext"]
names.rootdn=current[0]["rootDomainNamingContext"]
+ names.ncs=current[0]["namingContexts"]
+ names.dnsforestdn = None
+ names.dnsdomaindn = None
+
+ for i in range(0, len(names.ncs)):
+ nc = names.ncs[i]
+
+ dnsforestdn = "DC=ForestDnsZones,%s" % (str(names.rootdn))
+ if nc == dnsforestdn:
+ names.dnsforestdn = dnsforestdn
+ continue
+
+ dnsdomaindn = "DC=DomainDnsZones,%s" % (str(names.domaindn))
+ if nc == dnsdomaindn:
+ names.dnsdomaindn = dnsdomaindn
+ continue
+
# default site name
res3 = samdb.search(expression="(objectClass=site)",
base="CN=Sites," + configdn, scope=ldb.SCOPE_ONELEVEL, attrs=["cn"])
@@ -258,6 +290,36 @@ def find_provision_key_parameters(samdb, secretsdb, idmapdb, paths, smbconf,
names.root_gid = res9[0]["xidNumber"][0]
else:
names.root_gid = pwd.getpwuid(int(res9[0]["xidNumber"][0])).pw_gid
+
+ res10 = samdb.search(expression="(samaccountname=dns)",
+ scope=ldb.SCOPE_SUBTREE, attrs=["dn"],
+ controls=["search_options:1:2"])
+ if (len(res10) > 0):
+ has_legacy_dns_account = True
+ else:
+ has_legacy_dns_account = False
+
+ res11 = samdb.search(expression="(samaccountname=dns-%s)" % names.netbiosname,
+ scope=ldb.SCOPE_SUBTREE, attrs=["dn"],
+ controls=["search_options:1:2"])
+ if (len(res11) > 0):
+ has_dns_account = True
+ else:
+ has_dns_account = False
+
+ if names.dnsdomaindn is not None:
+ if has_dns_account:
+ names.dns_backend = 'BIND9_DLZ'
+ else:
+ names.dns_backend = 'SAMBA_INTERNAL'
+ elif has_dns_account or has_legacy_dns_account:
+ names.dns_backend = 'BIND9_FLATFILE'
+ else:
+ names.dns_backend = 'NONE'
+
+ dns_admins_sid = get_dnsadmins_sid(samdb, names.domaindn)
+ names.name_map['DnsAdmins'] = str(dns_admins_sid)
+
return names
@@ -1262,8 +1324,14 @@ def fill_samdb(samdb, lp, names, logger, domainsid, domainguid, policyguid,
# If we are setting up a subdomain, then this has been replicated in, so we don't need to add it
if fill == FILL_FULL:
logger.info("Setting up sam.ldb configuration data")
+
partitions_descr = b64encode(get_config_partitions_descriptor(domainsid))
sites_descr = b64encode(get_config_sites_descriptor(domainsid))
+ ntdsquotas_descr = b64encode(get_config_ntds_quotas_descriptor(domainsid))
+ protected1_descr = b64encode(get_config_delete_protected1_descriptor(domainsid))
+ protected1wd_descr = b64encode(get_config_delete_protected1wd_descriptor(domainsid))
+ protected2_descr = b64encode(get_config_delete_protected2_descriptor(domainsid))
+
setup_add_ldif(samdb, setup_path("provision_configuration.ldif"), {
"CONFIGDN": names.configdn,
"NETBIOSNAME": names.netbiosname,
@@ -1275,6 +1343,12 @@ def fill_samdb(samdb, lp, names, logger, domainsid, domainguid, policyguid,
"SERVERDN": names.serverdn,
"FOREST_FUNCTIONALITY": str(forestFunctionality),
"DOMAIN_FUNCTIONALITY": str(domainFunctionality),
+ "NTDSQUOTAS_DESCRIPTOR": ntdsquotas_descr,
+ "LOSTANDFOUND_DESCRIPTOR": protected1wd_descr,
+ "SERVICES_DESCRIPTOR": protected1_descr,
+ "PHYSICALLOCATIONS_DESCRIPTOR": protected1wd_descr,
+ "FORESTUPDATES_DESCRIPTOR": protected1wd_descr,
+ "EXTENDEDRIGHTS_DESCRIPTOR": protected2_descr,
"PARTITIONS_DESCRIPTOR": partitions_descr,
"SITES_DESCRIPTOR": sites_descr,
})
@@ -1287,6 +1361,13 @@ def fill_samdb(samdb, lp, names, logger, domainsid, domainguid, policyguid,
check_all_substituted(display_specifiers_ldif)
samdb.add_ldif(display_specifiers_ldif)
+ logger.info("Modifying display specifiers")
+ setup_modify_ldif(samdb,
+ setup_path("provision_configuration_modify.ldif"), {
+ "CONFIGDN": names.configdn,
+ "DISPLAYSPECIFIERS_DESCRIPTOR": protected2_descr
+ })
+
logger.info("Adding users container")
users_desc = b64encode(get_domain_users_descriptor(domainsid))
setup_add_ldif(samdb, setup_path("provision_users_add.ldif"), {
@@ -1308,6 +1389,8 @@ def fill_samdb(samdb, lp, names, logger, domainsid, domainguid, policyguid,
"DOMAINDN": names.domaindn})
logger.info("Setting up sam.ldb data")
infrastructure_desc = b64encode(get_domain_infrastructure_descriptor(domainsid))
+ lostandfound_desc = b64encode(get_domain_delete_protected2_descriptor(domainsid))
+ system_desc = b64encode(get_domain_delete_protected1_descriptor(domainsid))
builtin_desc = b64encode(get_domain_builtin_descriptor(domainsid))
controllers_desc = b64encode(get_domain_controllers_descriptor(domainsid))
setup_add_ldif(samdb, setup_path("provision.ldif"), {
@@ -1320,6 +1403,8 @@ def fill_samdb(samdb, lp, names, logger, domainsid, domainguid, policyguid,
"RIDAVAILABLESTART": str(next_rid + 600),
"POLICYGUID_DC": policyguid_dc,
"INFRASTRUCTURE_DESCRIPTOR": infrastructure_desc,
+ "LOSTANDFOUND_DESCRIPTOR": lostandfound_desc,
+ "SYSTEM_DESCRIPTOR": system_desc,
"BUILTIN_DESCRIPTOR": builtin_desc,
"DOMAIN_CONTROLLERS_DESCRIPTOR": controllers_desc,
})
@@ -1332,8 +1417,10 @@ def fill_samdb(samdb, lp, names, logger, domainsid, domainguid, policyguid,
"SCHEMADN": names.schemadn})
logger.info("Setting up well known security principals")
+ protected1wd_descr = b64encode(get_config_delete_protected1wd_descriptor(domainsid))
setup_add_ldif(samdb, setup_path("provision_well_known_sec_princ.ldif"), {
"CONFIGDN": names.configdn,
+ "WELLKNOWNPRINCIPALS_DESCRIPTOR": protected1wd_descr,
})
if fill == FILL_FULL or fill == FILL_SUBDOMAIN:
@@ -2041,6 +2128,7 @@ def provision(logger, session_info, credentials, smbconf=None,
adminpass = samba.generate_random_password(12, 32)
adminpass_generated = True
else:
+ adminpass = unicode(adminpass, 'utf-8')
adminpass_generated = False
if samdb_fill == FILL_FULL:
diff --git a/source4/scripting/python/samba/provision/descriptor.py b/source4/scripting/python/samba/provision/descriptor.py
index adf75797cc..32e91ed2b5 100644
--- a/source4/scripting/python/samba/provision/descriptor.py
+++ b/source4/scripting/python/samba/provision/descriptor.py
@@ -31,14 +31,22 @@ from samba.ndr import ndr_pack
# Descriptors of naming contexts and other important objects
-def get_empty_descriptor(domain_sid):
- sddl= ""
+def sddl2binary(sddl_in, domain_sid, name_map):
+ sddl = "%s" % sddl_in
+
+ for [name, sid] in name_map.items():
+ sddl = sddl.replace(name, sid)
+
sec = security.descriptor.from_sddl(sddl, domain_sid)
return ndr_pack(sec)
+def get_empty_descriptor(domain_sid, name_map={}):
+ sddl= ""
+ return sddl2binary(sddl, domain_sid, name_map)
+
# "get_schema_descriptor" is located in "schema.py"
-def get_config_descriptor(domain_sid):
+def get_config_descriptor(domain_sid, name_map={}):
sddl = "O:EAG:EAD:(OA;;CR;1131f6aa-9c07-11d1-f79f-00c04fc2dcd2;;ED)" \
"(OA;;CR;1131f6ab-9c07-11d1-f79f-00c04fc2dcd2;;ED)" \
"(OA;;CR;1131f6ac-9c07-11d1-f79f-00c04fc2dcd2;;ED)" \
@@ -54,10 +62,9 @@ def get_config_descriptor(domain_sid):
"(OA;;CR;1131f6aa-9c07-11d1-f79f-00c04fc2dcd2;;ER)" \
"S:(AU;SA;WPWOWD;;;WD)(AU;SA;CR;;;BA)(AU;SA;CR;;;DU)" \
"(OU;SA;CR;45ec5156-db7e-47bb-b53f-dbeb2d03c40f;;WD)"
- sec = security.descriptor.from_sddl(sddl, domain_sid)
- return ndr_pack(sec)
+ return sddl2binary(sddl, domain_sid, name_map)
-def get_config_partitions_descriptor(domain_sid):
+def get_config_partitions_descriptor(domain_sid, name_map={}):
sddl = "D:" \
"(A;;LCLORC;;;AU)" \
"(OA;;RP;e48d0154-bcf8-11d1-8702-00c04fb96050;;AU)" \
@@ -72,10 +79,9 @@ def get_config_partitions_descriptor(domain_sid):
"(OA;CIIO;WP;3df793df-9858-4417-a701-735a1ecebf74;bf967a8d-0de6-11d0-a285-00aa003049e2;BA)" \
"S:" \
"(AU;CISA;WPCRCCDCWOWDSDDT;;;WD)"
- sec = security.descriptor.from_sddl(sddl, domain_sid)
- return ndr_pack(sec)
+ return sddl2binary(sddl, domain_sid, name_map)
-def get_config_sites_descriptor(domain_sid):
+def get_config_sites_descriptor(domain_sid, name_map={}):
sddl = "D:" \
"(A;;RPLCLORC;;;AU)" \
"(OA;CIIO;SW;d31a8757-2447-4545-8081-3bb610cacbf2;f0f8ffab-1191-11d0-a060-00aa006c33ed;ER)" \
@@ -87,10 +93,37 @@ def get_config_sites_descriptor(domain_sid):
"(OU;CIIOSA;WP;f30e3bbe-9ff0-11d1-b603-0000f80367c1;bf967ab3-0de6-11d0-a285-00aa003049e2;WD)" \
"(OU;CIIOSA;WP;f30e3bbf-9ff0-11d1-b603-0000f80367c1;bf967ab3-0de6-11d0-a285-00aa003049e2;WD)" \
"(OU;CIIOSA;WP;3e10944c-c354-11d0-aff8-0000f80367c1;b7b13124-b82e-11d0-afee-0000f80367c1;WD)"
- sec = security.descriptor.from_sddl(sddl, domain_sid)
- return ndr_pack(sec)
+ return sddl2binary(sddl, domain_sid, name_map)
-def get_domain_descriptor(domain_sid):
+def get_config_ntds_quotas_descriptor(domain_sid, name_map={}):
+ sddl = "D:" \
+ "(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;EA)" \
+ "(A;;RPLCLORC;;;BA)" \
+ "(OA;;CR;4ecc03fe-ffc0-4947-b630-eb672a8a9dbc;;WD)"
+ return sddl2binary(sddl, domain_sid, name_map)
+
+def get_config_delete_protected1_descriptor(domain_sid, name_map={}):
+ sddl = "D:AI" \
+ "(A;;RPLCLORC;;;AU)" \
+ "(A;;RPWPCRCCLCLORCWOWDSW;;;EA)" \
+ "(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;SY)"
+ return sddl2binary(sddl, domain_sid, name_map)
+
+def get_config_delete_protected1wd_descriptor(domain_sid, name_map={}):
+ sddl = "D:AI" \
+ "(A;;RPLCLORC;;;WD)" \
+ "(A;;RPWPCRCCLCLORCWOWDSW;;;EA)" \
+ "(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;SY)"
+ return sddl2binary(sddl, domain_sid, name_map)
+
+def get_config_delete_protected2_descriptor(domain_sid, name_map={}):
+ sddl = "D:AI" \
+ "(A;;RPLCLORC;;;AU)" \
+ "(A;;RPWPCRCCDCLCLORCWOWDSW;;;EA)" \
+ "(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;SY)"
+ return sddl2binary(sddl, domain_sid, name_map)
+
+def get_domain_descriptor(domain_sid, name_map={}):
sddl= "O:BAG:BAD:AI(OA;CIIO;RP;4c164200-20c0-11d0-a768-00aa006e0529;4828cc14-1437-45bc-9b07-ad6f015e5f28;RU)" \
"(OA;CIIO;RP;4c164200-20c0-11d0-a768-00aa006e0529;bf967aba-0de6-11d0-a285-00aa003049e2;RU)" \
"(OA;CIIO;RP;5f202010-79a5-11d0-9020-00c04fc2d4cf;4828cc14-1437-45bc-9b07-ad6f015e5f28;RU)" \
@@ -140,20 +173,18 @@ def get_domain_descriptor(domain_sid):
"S:AI(OU;CISA;WP;f30e3bbe-9ff0-11d1-b603-0000f80367c1;bf967aa5-0de6-11d0-a285-00aa003049e2;WD)" \
"(OU;CISA;WP;f30e3bbf-9ff0-11d1-b603-0000f80367c1;bf967aa5-0de6-11d0-a285-00aa003049e2;WD)" \
"(AU;SA;CR;;;DU)(AU;SA;CR;;;BA)(AU;SA;WPWOWD;;;WD)"
- sec = security.descriptor.from_sddl(sddl, domain_sid)
- return ndr_pack(sec)
+ return sddl2binary(sddl, domain_sid, name_map)
-def get_domain_infrastructure_descriptor(domain_sid):
+def get_domain_infrastructure_descriptor(domain_sid, name_map={}):
sddl = "D:" \
"(A;;RPLCLORC;;;AU)" \
"(A;;RPWPCRCCLCLORCWOWDSW;;;DA)" \
"(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;SY)" \
"S:" \
"(AU;SA;WPCR;;;WD)"
- sec = security.descriptor.from_sddl(sddl, domain_sid)
- return ndr_pack(sec)
+ return sddl2binary(sddl, domain_sid, name_map)
-def get_domain_builtin_descriptor(domain_sid):
+def get_domain_builtin_descriptor(domain_sid, name_map={}):
sddl = "D:" \
"(OA;CIIO;RP;4c164200-20c0-11d0-a768-00aa006e0529;4828cc14-1437-45bc-9b07-ad6f015e5f28;RU)" \
"(OA;CIIO;RP;4c164200-20c0-11d0-a768-00aa006e0529;bf967aba-0de6-11d0-a285-00aa003049e2;RU)" \
@@ -207,10 +238,9 @@ def get_domain_builtin_descriptor(domain_sid):
"(AU;SA;CR;;;DU)" \
"(AU;SA;CR;;;BA)" \
"(AU;SA;WPWOWD;;;WD)"
- sec = security.descriptor.from_sddl(sddl, domain_sid)
- return ndr_pack(sec)
+ return sddl2binary(sddl, domain_sid, name_map)
-def get_domain_computers_descriptor(domain_sid):
+def get_domain_computers_descriptor(domain_sid, name_map={}):
sddl = "D:" \
"(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;SY)" \
"(A;;RPWPCRCCDCLCLORCWOWDSW;;;DA)" \
@@ -221,10 +251,9 @@ def get_domain_computers_descriptor(domain_sid):
"(A;;RPLCLORC;;;AU)" \
"(OA;;CCDC;4828cc14-1437-45bc-9b07-ad6f015e5f28;;AO)" \
"S:"
- sec = security.descriptor.from_sddl(sddl, domain_sid)
- return ndr_pack(sec)
+ return sddl2binary(sddl, domain_sid, name_map)
-def get_domain_users_descriptor(domain_sid):
+def get_domain_users_descriptor(domain_sid, name_map={}):
sddl = "D:" \
"(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;SY)" \
"(A;;RPWPCRCCDCLCLORCWOWDSW;;;DA)" \
@@ -234,10 +263,9 @@ def get_domain_users_descriptor(domain_sid):
"(A;;RPLCLORC;;;AU)" \
"(OA;;CCDC;4828cc14-1437-45bc-9b07-ad6f015e5f28;;AO)" \
"S:"
- sec = security.descriptor.from_sddl(sddl, domain_sid)
- return ndr_pack(sec)
+ return sddl2binary(sddl, domain_sid, name_map)
-def get_domain_controllers_descriptor(domain_sid):
+def get_domain_controllers_descriptor(domain_sid, name_map={}):
sddl = "D:" \
"(A;;RPLCLORC;;;AU)" \
"(A;;RPWPCRCCLCLORCWOWDSW;;;DA)" \
@@ -246,10 +274,23 @@ def get_domain_controllers_descriptor(domain_sid):
"S:" \
"(AU;SA;CCDCWOWDSDDT;;;WD)" \
"(AU;CISA;WP;;;WD)"
- sec = security.descriptor.from_sddl(sddl, domain_sid)
- return ndr_pack(sec)
+ return sddl2binary(sddl, domain_sid, name_map)
-def get_dns_partition_descriptor(domainsid):
+def get_domain_delete_protected1_descriptor(domain_sid, name_map={}):
+ sddl = "D:AI" \
+ "(A;;RPLCLORC;;;AU)" \
+ "(A;;RPWPCRCCLCLORCWOWDSW;;;DA)" \
+ "(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;SY)"
+ return sddl2binary(sddl, domain_sid, name_map)
+
+def get_domain_delete_protected2_descriptor(domain_sid, name_map={}):
+ sddl = "D:AI" \
+ "(A;;RPLCLORC;;;AU)" \
+ "(A;;RPWPCRCCDCLCLORCWOWDSW;;;DA)" \
+ "(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;SY)"
+ return sddl2binary(sddl, domain_sid, name_map)
+
+def get_dns_partition_descriptor(domain_sid, name_map={}):
sddl = "O:SYG:BAD:AI" \
"(OA;CIIO;RP;4c164200-20c0-11d0-a768-00aa006e0529;4828cc14-1437-45bc-9b07-ad6f015e5f28;RU)" \
"(OA;CIIO;RP;4c164200-20c0-11d0-a768-00aa006e0529;bf967aba-0de6-11d0-a285-00aa003049e2;RU)" \
@@ -301,5 +342,18 @@ def get_dns_partition_descriptor(domainsid):
"(OU;CISA;WP;f30e3bbe-9ff0-11d1-b603-0000f80367c1;bf967aa5-0de6-11d0-a285-00aa003049e2;WD)" \
"(OU;CISA;WP;f30e3bbf-9ff0-11d1-b603-0000f80367c1;bf967aa5-0de6-11d0-a285-00aa003049e2;WD)" \
"(AU;SA;CR;;;DU)(AU;SA;CR;;;BA)(AU;SA;WPWOWD;;;WD)"
- sec = security.descriptor.from_sddl(sddl, domainsid)
- return ndr_pack(sec)
+ return sddl2binary(sddl, domain_sid, name_map)
+
+def get_dns_forest_microsoft_dns_descriptor(domain_sid, name_map={}):
+ sddl = "O:SYG:SYD:AI" \
+ "(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;SY)" \
+ "(A;CI;RPWPCRCCDCLCRCWOWDSDDTSW;;;ED)"
+ return sddl2binary(sddl, domain_sid, name_map)
+
+def get_dns_domain_microsoft_dns_descriptor(domain_sid, name_map={}):
+ sddl = "O:SYG:SYD:AI" \
+ "(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;DA)" \
+ "(A;CI;RPWPCRCCDCLCRCWOWDSDDTSW;;;DnsAdmins)" \
+ "(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;SY)" \
+ "(A;CI;RPWPCRCCDCLCRCWOWDSDDTSW;;;ED)"
+ return sddl2binary(sddl, domain_sid, name_map)
diff --git a/source4/scripting/python/samba/provision/sambadns.py b/source4/scripting/python/samba/provision/sambadns.py
index a66fde1425..740dd38417 100644
--- a/source4/scripting/python/samba/provision/sambadns.py
+++ b/source4/scripting/python/samba/provision/sambadns.py
@@ -37,7 +37,11 @@ from samba.dsdb import (
)
from samba.provision.descriptor import (
get_domain_descriptor,
- get_dns_partition_descriptor
+ get_domain_delete_protected1_descriptor,
+ get_domain_delete_protected2_descriptor,
+ get_dns_partition_descriptor,
+ get_dns_forest_microsoft_dns_descriptor,
+ get_dns_domain_microsoft_dns_descriptor
)
from samba.provision.common import (
setup_path,
@@ -244,6 +248,8 @@ def setup_dns_partitions(samdb, domainsid, domaindn, forestdn, configdn,
domainzone_dns = ldb.Dn(samdb, domainzone_dn).canonical_ex_str().strip()
forestzone_dns = ldb.Dn(samdb, forestzone_dn).canonical_ex_str().strip()
+ protected1_desc = get_domain_delete_protected1_descriptor(domainsid)
+ protected2_desc = get_domain_delete_protected2_descriptor(domainsid)
setup_add_ldif(samdb, setup_path("provision_dnszones_add.ldif"), {
"DOMAINZONE_DN": domainzone_dn,
"FORESTZONE_DN": forestzone_dn,
@@ -253,6 +259,8 @@ def setup_dns_partitions(samdb, domainsid, domaindn, forestdn, configdn,
"FORESTZONE_DNS": forestzone_dns,
"CONFIGDN": configdn,
"SERVERDN": serverdn,
+ "LOSTANDFOUND_DESCRIPTOR": b64encode(protected2_desc),
+ "INFRASTRUCTURE_DESCRIPTOR": b64encode(protected1_desc),
})
setup_modify_ldif(samdb, setup_path("provision_dnszones_modify.ldif"), {
@@ -269,18 +277,18 @@ def add_dns_accounts(samdb, domaindn):
})
-def add_dns_container(samdb, domaindn, prefix, domainsid, dnsadmins_sid):
+def add_dns_container(samdb, domaindn, prefix, domain_sid, dnsadmins_sid, forest=False):
+ name_map = {'DnsAdmins': str(dnsadmins_sid)}
+ if forest is True:
+ sd_val = get_dns_forest_microsoft_dns_descriptor(domain_sid,
+ name_map=name_map)
+ else:
+ sd_val = get_dns_domain_microsoft_dns_descriptor(domain_sid,
+ name_map=name_map)
# CN=MicrosoftDNS,<PREFIX>,<DOMAINDN>
- sddl = "O:SYG:SYD:AI" \
- "(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;DA)" \
- "(A;CI;RPWPCRCCDCLCRCWOWDSDDTSW;;;%s)" \
- "(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;SY)" \
- "(A;CI;RPWPCRCCDCLCRCWOWDSDDTSW;;;ED)" \
- "S:AI" % dnsadmins_sid
- sec = security.descriptor.from_sddl(sddl, domainsid)
msg = ldb.Message(ldb.Dn(samdb, "CN=MicrosoftDNS,%s,%s" % (prefix, domaindn)))
msg["objectClass"] = ["top", "container"]
- msg["nTSecurityDescriptor"] = ldb.MessageElement(ndr_pack(sec), ldb.FLAG_MOD_ADD,
+ msg["nTSecurityDescriptor"] = ldb.MessageElement(sd_val, ldb.FLAG_MOD_ADD,
"nTSecurityDescriptor")
samdb.add(msg)
@@ -942,7 +950,7 @@ def create_dns_partitions(samdb, domainsid, names, domaindn, forestdn,
add_dns_container(samdb, domaindn, "DC=DomainDnsZones", domainsid,
dnsadmins_sid)
add_dns_container(samdb, forestdn, "DC=ForestDnsZones", domainsid,
- dnsadmins_sid)
+ dnsadmins_sid, forest=True)
def fill_dns_data_partitions(samdb, domainsid, site, domaindn, forestdn,
diff --git a/source4/scripting/python/samba/samdb.py b/source4/scripting/python/samba/samdb.py
index d83e0a6f7c..5478e24c34 100644
--- a/source4/scripting/python/samba/samdb.py
+++ b/source4/scripting/python/samba/samdb.py
@@ -449,12 +449,13 @@ member: %s
if len(res) > 1:
raise Exception('Matched %u multiple users with filter "%s"' % (len(res), search_filter))
user_dn = res[0].dn
+ pw = unicode('"' + password + '"', 'utf-8').encode('utf-16-le')
setpw = """
dn: %s
changetype: modify
replace: unicodePwd
unicodePwd:: %s
-""" % (user_dn, base64.b64encode(("\"" + password + "\"").encode('utf-16-le')))
+""" % (user_dn, base64.b64encode(pw))
self.modify_ldif(setpw)
diff --git a/source4/scripting/python/samba/schema.py b/source4/scripting/python/samba/schema.py
index 2d1315093b..5c8f506f26 100644
--- a/source4/scripting/python/samba/schema.py
+++ b/source4/scripting/python/samba/schema.py
@@ -32,7 +32,7 @@ from samba import dsdb
from ldb import SCOPE_SUBTREE, SCOPE_ONELEVEL
import os
-def get_schema_descriptor(domain_sid):
+def get_schema_descriptor(domain_sid, name_map={}):
sddl = "O:SAG:SAD:AI(OA;;CR;e12b56b6-0a95-11d1-adbb-00c04fd8d5cd;;SA)" \
"(OA;;CR;1131f6aa-9c07-11d1-f79f-00c04fc2dcd2;;ED)" \
"(OA;;CR;1131f6ab-9c07-11d1-f79f-00c04fc2dcd2;;ED)" \
diff --git a/source4/scripting/python/samba/upgradehelpers.py b/source4/scripting/python/samba/upgradehelpers.py
index 81fb8dc0f4..8427f6ae37 100644
--- a/source4/scripting/python/samba/upgradehelpers.py
+++ b/source4/scripting/python/samba/upgradehelpers.py
@@ -242,7 +242,6 @@ def newprovision(names, creds, session, smbconf, provdir, logger):
shutil.rmtree(provdir)
os.mkdir(provdir)
logger.info("Provision stored in %s", provdir)
- dns_backend="BIND9_DLZ"
return provision(logger, session, creds, smbconf=smbconf,
targetdir=provdir, samdb_fill=FILL_FULL, realm=names.realm,
domain=names.domain, domainguid=names.domainguid,
@@ -255,7 +254,7 @@ def newprovision(names, creds, session, smbconf, provdir, logger):
serverrole="domain controller",
backend_type=None, ldapadminpass=None, ol_mmr_urls=None,
slapd_path=None,
- dom_for_fun_level=names.domainlevel, dns_backend=dns_backend,
+ dom_for_fun_level=names.domainlevel, dns_backend=names.dns_backend,
useeadb=True, use_ntvfs=True)