LDBBackend,
OpenLDAPBackend,
)
+from samba.provision.sambadns import setup_ad_dns
+
import samba.param
import samba.registry
from samba.schema import Schema
from samba.samdb import SamDB
+from samba.dbchecker import dbcheck
+
VALID_NETBIOS_CHARS = " !#$%&'()-.@^_{}~"
DEFAULT_POLICY_GUID = "31B2F340-016D-11D2-945F-00C04FB984F9"
tab = []
if not replace:
- entry = samdb.search(expression="(&(dn=@PROVISION)(%s=*))" %
- LAST_PROVISION_USN_ATTRIBUTE, base="",
- scope=ldb.SCOPE_SUBTREE,
- attrs=[LAST_PROVISION_USN_ATTRIBUTE, "dn"])
+ entry = samdb.search(base="@PROVISION",
+ scope=ldb.SCOPE_BASE,
+ attrs=[LAST_PROVISION_USN_ATTRIBUTE, "dn"])
for e in entry[0][LAST_PROVISION_USN_ATTRIBUTE]:
if not re.search(';', e):
e = "%s;%s" % (e, id)
delta.dn = ldb.Dn(samdb, "@PROVISION")
delta[LAST_PROVISION_USN_ATTRIBUTE] = ldb.MessageElement(tab,
ldb.FLAG_MOD_REPLACE, LAST_PROVISION_USN_ATTRIBUTE)
- entry = samdb.search(expression="(&(dn=@PROVISION)(provisionnerID=*))",
- base="", scope=ldb.SCOPE_SUBTREE,
- attrs=["provisionnerID"])
+ entry = samdb.search(expression='provisionnerID=*',
+ base="@PROVISION", scope=ldb.SCOPE_BASE,
+ attrs=["provisionnerID"])
if len(entry) == 0 or len(entry[0]) == 0:
delta["provisionnerID"] = ldb.MessageElement(id, ldb.FLAG_MOD_ADD, "provisionnerID")
samdb.modify(delta)
:return: a dictionnary which keys are invocation id and values are an array
of integer representing the different ranges
"""
- entry = sam.search(expression="(&(dn=@PROVISION)(%s=*))" %
- LAST_PROVISION_USN_ATTRIBUTE,
- base="", scope=ldb.SCOPE_SUBTREE,
- attrs=[LAST_PROVISION_USN_ATTRIBUTE, "provisionnerID"])
+ try:
+ entry = sam.search(expression="%s=*" % LAST_PROVISION_USN_ATTRIBUTE,
+ base="@PROVISION", scope=ldb.SCOPE_BASE,
+ attrs=[LAST_PROVISION_USN_ATTRIBUTE, "provisionnerID"])
+ except ldb.LdbError, (ecode, emsg):
+ if ecode == ldb.ERR_NO_SUCH_OBJECT:
+ return None
+ raise
if len(entry):
myids = []
range = {}
if targetdir is not None:
privatedir_line = "private dir = " + os.path.abspath(os.path.join(targetdir, "private"))
lockdir_line = "lock dir = " + os.path.abspath(targetdir)
+ statedir_line = "state directory = " + os.path.abspath(targetdir)
+ cachedir_line = "cache directory = " + os.path.abspath(targetdir)
lp.set("lock dir", os.path.abspath(targetdir))
+ lp.set("state directory", os.path.abspath(targetdir))
+ lp.set("cache directory", os.path.abspath(targetdir))
else:
privatedir_line = ""
lockdir_line = ""
+ statedir_line = ""
+ cachedir_line = ""
- sysvol = os.path.join(lp.get("lock dir"), "sysvol")
+ sysvol = os.path.join(lp.get("state directory"), "sysvol")
netlogon = os.path.join(sysvol, realm.lower(), "scripts")
setup_file(setup_path("provision.smb.conf.%s" % smbconfsuffix),
"NETLOGONPATH": netlogon,
"SYSVOLPATH": sysvol,
"PRIVATEDIR_LINE": privatedir_line,
- "LOCKDIR_LINE": lockdir_line
+ "LOCKDIR_LINE": lockdir_line,
+ "STATEDIR_LINE": statedir_line,
+ "CACHEDIR_LINE": cachedir_line
})
# reload the smb.conf
def setup_self_join(samdb, names, machinepass, dnspass,
domainsid, next_rid, invocationid,
policyguid, policyguid_dc, domainControllerFunctionality,
- ntdsguid):
+ ntdsguid, dc_rid=None):
"""Join a host to its own domain."""
assert isinstance(invocationid, str)
if ntdsguid is not None:
ntdsguid_line = "objectGUID: %s\n"%ntdsguid
else:
ntdsguid_line = ""
+
+ if dc_rid is None:
+ dc_rid = next_rid
+
setup_add_ldif(samdb, setup_path("provision_self_join.ldif"), {
"CONFIGDN": names.configdn,
"SCHEMADN": names.schemadn,
"DNSNAME": "%s.%s" % (names.hostname, names.dnsdomain),
"MACHINEPASS_B64": b64encode(machinepass.encode('utf-16-le')),
"DOMAINSID": str(domainsid),
- "DCRID": str(next_rid),
+ "DCRID": str(dc_rid),
"SAMBA_VERSION_STRING": version,
"NTDSGUID": ntdsguid_line,
"DOMAIN_CONTROLLER_FUNCTIONALITY": str(
"RIDALLOCATIONEND": str(next_rid + 100 + 499),
})
- # This is partially Samba4 specific and should be replaced by the correct
+ # This is Samba4 specific and should be replaced by the correct
# DNS AD-style setup
- setup_add_ldif(samdb, setup_path("provision_dns_add.ldif"), {
+ setup_add_ldif(samdb, setup_path("provision_dns_add_samba.ldif"), {
"DNSDOMAIN": names.dnsdomain,
"DOMAINDN": names.domaindn,
"DNSPASS_B64": b64encode(dnspass.encode('utf-16-le')),
logger, domainsid, domainguid, policyguid, policyguid_dc, fill,
adminpass, krbtgtpass, machinepass, invocationid, dnspass, ntdsguid,
serverrole, am_rodc=False, dom_for_fun_level=None, schema=None,
- next_rid=1000):
+ next_rid=None, dc_rid=None):
"""Setup a complete SAM Database.
:note: This will wipe the main SAM database file!
"""
+ if next_rid is None:
+ next_rid = 1000
+
# Provision does not make much sense values larger than 1000000000
# as the upper range of the rIDAvailablePool is 1073741823 and
# we don't want to create a domain that cannot allocate rids.
setup_modify_ldif(samdb, setup_path("provision_basedn_modify.ldif"), {
"DOMAINDN": names.domaindn,
- "CREATTIME": str(int(time.time() * 1e7)), # seconds -> ticks
+ "CREATTIME": str(samba.unix2nttime(int(time.time()))),
"NEXTRID": str(next_rid),
"DEFAULTSITE": names.sitename,
"CONFIGDN": names.configdn,
"DOMAINDN": names.domaindn})
logger.info("Setting up sam.ldb data")
setup_add_ldif(samdb, setup_path("provision.ldif"), {
- "CREATTIME": str(int(time.time() * 1e7)), # seconds -> ticks
+ "CREATTIME": str(samba.unix2nttime(int(time.time()))),
"DOMAINDN": names.domaindn,
"NETBIOSNAME": names.netbiosname,
"DEFAULTSITE": names.sitename,
logger.info("Setting up self join")
setup_self_join(samdb, names=names, invocationid=invocationid,
- dnspass=dnspass,
- machinepass=machinepass,
- domainsid=domainsid,
- next_rid=next_rid,
- policyguid=policyguid,
- policyguid_dc=policyguid_dc,
- domainControllerFunctionality=domainControllerFunctionality,
- ntdsguid=ntdsguid)
+ dnspass=dnspass,
+ machinepass=machinepass,
+ domainsid=domainsid,
+ next_rid=next_rid,
+ dc_rid=dc_rid,
+ policyguid=policyguid,
+ policyguid_dc=policyguid_dc,
+ domainControllerFunctionality=domainControllerFunctionality,
+ ntdsguid=ntdsguid)
ntds_dn = "CN=NTDS Settings,%s" % names.serverdn
names.ntdsguid = samdb.searchone(basedn=ntds_dn,
targetdir=None, samdb_fill=FILL_FULL, realm=None, rootdn=None,
domaindn=None, schemadn=None, configdn=None, serverdn=None,
domain=None, hostname=None, hostip=None, hostip6=None, domainsid=None,
- next_rid=1000, adminpass=None, ldapadminpass=None, krbtgtpass=None,
+ next_rid=1000, dc_rid=None, adminpass=None, ldapadminpass=None, krbtgtpass=None,
domainguid=None, policyguid=None, policyguid_dc=None,
invocationid=None, machinepass=None, ntdsguid=None, dnspass=None,
root=None, nobody=None, users=None, wheel=None, backup=None, aci=None,
invocationid=invocationid, machinepass=machinepass,
dnspass=dnspass, ntdsguid=ntdsguid, serverrole=serverrole,
dom_for_fun_level=dom_for_fun_level, am_rodc=am_rodc,
- next_rid=next_rid)
+ next_rid=next_rid, dc_rid=dc_rid)
if serverrole == "domain controller":
if paths.netlogon is None:
domainsid, names.dnsdomain, names.domaindn, lp)
logger.info("Setting up sam.ldb rootDSE marking as synchronized")
- setup_modify_ldif(samdb, setup_path("provision_rootdse_modify.ldif"))
+ setup_modify_ldif(samdb, setup_path("provision_rootdse_modify.ldif"),
+ { 'NTDSGUID' : names.ntdsguid })
secretsdb_self_join(secrets_ldb, domain=names.domain,
realm=names.realm, dnsdomain=names.dnsdomain,
dnsdomain=names.dnsdomain,
dns_keytab_path=paths.dns_keytab, dnspass=dnspass)
+ setup_ad_dns(samdb, names=names, hostip=hostip, hostip6=hostip6)
+
domainguid = samdb.searchone(basedn=domaindn,
attribute="objectGUID")
assert isinstance(domainguid, str)
logger.info("Failed to chown %s to bind gid %u",
dns_keytab_path, paths.bind_gid)
+ if samdb_fill != FILL_DRS:
+ # fix any dangling GUIDs from the provision
+ logger.info("Fixing provision GUIDs")
+ chk = dbcheck(samdb, samdb_schema=samdb, verbose=False, fix=True, yes=True, quiet=True)
+ samdb.transaction_start()
+ # a small number of GUIDs are missing because of ordering issues in the
+ # provision code
+ for schema_obj in ['CN=Domain', 'CN=Organizational-Person', 'CN=Contact', 'CN=inetOrgPerson']:
+ chk.check_database(DN="%s,%s" % (schema_obj, names.schemadn),
+ scope=ldb.SCOPE_BASE, attrs=['defaultObjectCategory'])
+ chk.check_database(DN="CN=IP Security,CN=System,%s" % names.domaindn,
+ scope=ldb.SCOPE_ONELEVEL,
+ attrs=['ipsecOwnersReference',
+ 'ipsecFilterReference',
+ 'ipsecISAKMPReference',
+ 'ipsecNegotiationPolicyReference',
+ 'ipsecNFAReference'])
+ samdb.transaction_commit()
+
logger.info("Please install the phpLDAPadmin configuration located at %s into /etc/phpldapadmin/config.php",
paths.phpldapadminconfig)