import samba.ntacls
from samba.join import join_RODC, join_DC, join_subdomain
from samba.auth import system_session
-from samba.samdb import SamDB
+from samba.samdb import SamDB, get_default_backend_store
from samba.ndr import ndr_unpack, ndr_pack, ndr_print
from samba.dcerpc import drsuapi
from samba.dcerpc import drsblobs
Option("--plaintext-secrets", action="store_true",
help="Store secret/sensitive values as plain text on disk" +
"(default is to encrypt secret/ensitive values)"),
+ Option("--backend-store", type="choice", metavar="BACKENDSTORE",
+ choices=["tdb", "mdb"],
+ help="Specify the database backend to be used "
+ "(default is %s)" % get_default_backend_store()),
]
openldap_options = [
ldap_backend_forced_uri=None,
ldap_dryrun_mode=None,
base_schema=None,
- plaintext_secrets=False):
+ plaintext_secrets=False,
+ backend_store=None):
self.logger = self.get_logger("provision")
if quiet:
domain_sid = security.dom_sid(domain_sid)
session = system_session()
+ if backend_store is None:
+ backend_store = get_default_backend_store()
try:
result = provision(self.logger,
session, smbconf=smbconf, targetdir=targetdir,
ldap_backend_forced_uri=ldap_backend_forced_uri,
nosync=ldap_backend_nosync, ldap_dryrun_mode=ldap_dryrun_mode,
base_schema=base_schema,
- plaintext_secrets=plaintext_secrets)
+ plaintext_secrets=plaintext_secrets,
+ backend_store=backend_store)
except ProvisioningError as e:
raise CommandError("Provision failed", e)
from samba.samdb import SamDB
from samba.dbchecker import dbcheck
from samba.provision.kerberos import create_kdc_conf
+from samba.samdb import get_default_backend_store
DEFAULT_POLICY_GUID = "31B2F340-016D-11D2-945F-00C04FB984F9"
DEFAULT_DC_POLICY_GUID = "6AC1786C-016F-11D2-945F-00C04FB984F9"
def setup_samdb_partitions(samdb_path, logger, lp, session_info,
provision_backend, names, serverrole,
- erase=False, plaintext_secrets=False):
+ erase=False, plaintext_secrets=False,
+ backend_store=None):
"""Setup the partitions for the SAM database.
Alternatively, provision() may call this, and then populate the database.
if not plaintext_secrets:
required_features = "requiredFeatures: encryptedSecrets"
+ if backend_store is None:
+ backend_store = get_default_backend_store()
+ backend_store_line = "backendStore: %s" % backend_store
+
samdb.transaction_start()
try:
logger.info("Setting up sam.ldb partitions and settings")
setup_add_ldif(samdb, setup_path("provision_partitions.ldif"), {
- "LDAP_BACKEND_LINE": ldap_backend_line
+ "LDAP_BACKEND_LINE": ldap_backend_line,
+ "BACKEND_STORE": backend_store_line
})
def setup_samdb(path, session_info, provision_backend, lp, names,
logger, fill, serverrole, schema, am_rodc=False,
- plaintext_secrets=False):
+ plaintext_secrets=False, backend_store=None):
"""Setup a complete SAM Database.
:note: This will wipe the main SAM database file!
# Also wipes the database
setup_samdb_partitions(path, logger=logger, lp=lp,
provision_backend=provision_backend, session_info=session_info,
- names=names, serverrole=serverrole, plaintext_secrets=plaintext_secrets)
+ names=names, serverrole=serverrole, plaintext_secrets=plaintext_secrets,
+ backend_store=backend_store)
# Load the database, but don's load the global schema and don't connect
# quite yet
def fill_samdb(samdb, lp, names, logger, policyguid,
policyguid_dc, fill, adminpass, krbtgtpass, machinepass, dns_backend,
dnspass, invocationid, ntdsguid, serverrole, am_rodc=False,
- dom_for_fun_level=None, schema=None, next_rid=None, dc_rid=None):
+ dom_for_fun_level=None, schema=None, next_rid=None, dc_rid=None,
+ backend_store=None):
if next_rid is None:
next_rid = 1000
invocationid=None, machinepass=None, ntdsguid=None,
dns_backend=None, dnspass=None,
serverrole=None, dom_for_fun_level=None,
- am_rodc=False, lp=None, use_ntvfs=False, skip_sysvolacl=False):
+ am_rodc=False, lp=None, use_ntvfs=False,
+ skip_sysvolacl=False, backend_store=None):
# create/adapt the group policy GUIDs
# Default GUID for default policy are described at
# "How Core Group Policy Works"
dns_backend=dns_backend, dnspass=dnspass,
ntdsguid=ntdsguid, serverrole=serverrole,
dom_for_fun_level=dom_for_fun_level, am_rodc=am_rodc,
- next_rid=next_rid, dc_rid=dc_rid)
+ next_rid=next_rid, dc_rid=dc_rid,
+ backend_store=backend_store)
# Set up group policies (domain policy and domain controller
# policy)
setup_ad_dns(samdb, secrets_ldb, names, paths, lp, logger,
hostip=hostip, hostip6=hostip6, dns_backend=dns_backend,
dnspass=dnspass, os_level=dom_for_fun_level,
- targetdir=targetdir, fill_level=samdb_fill)
+ targetdir=targetdir, fill_level=samdb_fill,
+ backend_store=backend_store)
domainguid = samdb.searchone(basedn=samdb.get_default_basedn(),
attribute="objectGUID")
use_rfc2307=False, maxuid=None, maxgid=None, skip_sysvolacl=True,
ldap_backend_forced_uri=None, nosync=False, ldap_dryrun_mode=False,
ldap_backend_extra_port=None, base_schema=None,
- plaintext_secrets=False):
+ plaintext_secrets=False, backend_store=None):
"""Provision samba4
:note: caution, this wipes all existing data!
if backend_type is None:
backend_type = "ldb"
+ if backend_store is None:
+ backend_store = get_default_backend_store()
if domainsid is None:
domainsid = security.random_sid()
provision_backend, lp, names, logger=logger,
serverrole=serverrole,
schema=schema, fill=samdb_fill, am_rodc=am_rodc,
- plaintext_secrets=plaintext_secrets)
+ plaintext_secrets=plaintext_secrets,
+ backend_store=backend_store)
if serverrole == "active directory domain controller":
if paths.netlogon is None:
dnspass=dnspass, serverrole=serverrole,
dom_for_fun_level=dom_for_fun_level, am_rodc=am_rodc,
lp=lp, use_ntvfs=use_ntvfs,
- skip_sysvolacl=skip_sysvolacl)
+ skip_sysvolacl=skip_sysvolacl,
+ backend_store=backend_store)
if not is_heimdal_built():
create_kdc_conf(paths.kdcconf, realm, domain, os.path.dirname(lp.get("log file")))
import subprocess
import samba
from samba.tdb_util import tdb_copy
+from samba.mdb_util import mdb_copy
from samba.ndr import ndr_pack, ndr_unpack
from samba import setup_file
from samba.dcerpc import dnsp, misc, security
FILL_DRS,
)
+from samba.samdb import get_default_backend_store
def get_domainguid(samdb, domaindn):
res = samdb.search(base=domaindn, scope=ldb.SCOPE_BASE, attrs=["objectGUID"])
# Find the partitions and corresponding filenames
partfile = {}
- res = samdb.search(base="@PARTITION", scope=ldb.SCOPE_BASE, attrs=["partition"])
+ res = samdb.search(base="@PARTITION",
+ scope=ldb.SCOPE_BASE,
+ attrs=["partition", "backendStore"])
for tmp in res[0]["partition"]:
(nc, fname) = tmp.split(':')
partfile[nc.upper()] = fname
+ backend_store = get_default_backend_store()
+ if "backendStore" in res[0]:
+ backend_store = res[0]["backendStore"][0]
+
# Create empty domain partition
+
domaindn = names.domaindn.upper()
domainpart_file = os.path.join(dns_dir, partfile[domaindn])
try:
file(domainpart_file, 'w').close()
# Fill the basedn and @OPTION records in domain partition
- dom_ldb = samba.Ldb(domainpart_file)
+ dom_url = "%s://%s" % (backend_store, domainpart_file)
+ dom_ldb = samba.Ldb(dom_url)
domainguid_line = "objectGUID: %s\n-" % domainguid
descr = b64encode(get_domain_descriptor(domainsid))
setup_add_ldif(dom_ldb, setup_path("provision_basedn.ldif"), {
os.path.join(dns_dir, "sam.ldb"))
for nc in partfile:
pfile = partfile[nc]
- tdb_copy(os.path.join(private_dir, pfile),
- os.path.join(dns_dir, pfile))
+ if backend_store == "mdb":
+ mdb_copy(os.path.join(private_dir, pfile),
+ os.path.join(dns_dir, pfile))
+ else:
+ tdb_copy(os.path.join(private_dir, pfile),
+ os.path.join(dns_dir, pfile))
except:
logger.error(
"Failed to setup database for BIND, AD based DNS cannot be used")
os.chown(dpath, -1, paths.bind_gid)
os.chmod(dpath, 0o770)
for f in files:
- if f.endswith('.ldb') or f.endswith('.tdb'):
+ if f.endswith(('.ldb', '.tdb', 'ldb-lock')):
fpath = os.path.join(dirname, f)
os.chown(fpath, -1, paths.bind_gid)
os.chmod(fpath, 0o660)
def setup_ad_dns(samdb, secretsdb, names, paths, lp, logger,
dns_backend, os_level, dnspass=None, hostip=None, hostip6=None,
- targetdir=None, fill_level=FILL_FULL):
+ targetdir=None, fill_level=FILL_FULL, backend_store=None):
"""Provision DNS information (assuming GC role)
:param samdb: LDB object connected to sam.ldb file
if dns_backend.startswith("BIND9_"):
setup_bind9_dns(samdb, secretsdb, names, paths, lp, logger,
dns_backend, os_level, site=site, dnspass=dnspass, hostip=hostip,
- hostip6=hostip6, targetdir=targetdir)
+ hostip6=hostip6, targetdir=targetdir,
+ backend_store=backend_store)
def setup_bind9_dns(samdb, secretsdb, names, paths, lp, logger,
dns_backend, os_level, site=None, dnspass=None, hostip=None,
- hostip6=None, targetdir=None, key_version_number=None):
+ hostip6=None, targetdir=None, key_version_number=None,
+ backend_store=None):
"""Provision DNS information (assuming BIND9 backend in DC role)
:param samdb: LDB object connected to sam.ldb file
ntdsguid=names.ntdsguid)
if dns_backend == "BIND9_DLZ" and os_level >= DS_DOMAIN_FUNCTION_2003:
- create_samdb_copy(samdb, logger, paths, names, names.domainsid, domainguid)
+ create_samdb_copy(samdb, logger, paths,
+ names, names.domainsid, domainguid)
create_named_conf(paths, realm=names.realm,
dnsdomain=names.dnsdomain, dns_backend=dns_backend,
__docformat__ = "restructuredText"
+def get_default_backend_store():
+ return "tdb"
+
class SamDB(samba.Ldb):
"""The SAM database."""
replicateEntries: @ATTRIBUTES
replicateEntries: @INDEXLIST
replicateEntries: @OPTIONS
+${BACKEND_STORE}
${LDAP_BACKEND_LINE}