diff options
Diffstat (limited to 'python/samba/provision')
-rw-r--r-- | python/samba/provision/__init__.py | 40 | ||||
-rw-r--r-- | python/samba/provision/backend.py | 737 |
2 files changed, 9 insertions, 768 deletions
diff --git a/python/samba/provision/__init__.py b/python/samba/provision/__init__.py index 2ffaf9fc250..217840989aa 100644 --- a/python/samba/provision/__init__.py +++ b/python/samba/provision/__init__.py @@ -77,9 +77,7 @@ from samba.ms_display_specifiers import read_ms_ldif from samba.ntacls import setntacl, getntacl, dsacl2fsacl from samba.ndr import ndr_pack, ndr_unpack from samba.provision.backend import ( - FDSBackend, LDBBackend, - OpenLDAPBackend, ) from samba.descriptor import ( get_empty_descriptor, @@ -2162,13 +2160,11 @@ def provision(logger, session_info, smbconf=None, krbtgtpass=None, domainguid=None, policyguid=None, policyguid_dc=None, dns_backend=None, dns_forwarder=None, dnspass=None, invocationid=None, machinepass=None, ntdsguid=None, - root=None, nobody=None, users=None, backup=None, aci=None, - serverrole=None, dom_for_fun_level=None, backend_type=None, - sitename=None, ol_mmr_urls=None, ol_olc=None, slapd_path=None, + root=None, nobody=None, users=None, backup=None, + sitename=None, serverrole=None, dom_for_fun_level=None, useeadb=False, am_rodc=False, lp=None, use_ntvfs=False, 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="2012_R2", + base_schema="2012_R2", plaintext_secrets=False, backend_store=None, backend_store_size=None, batch_mode=False): """Provision samba4 @@ -2185,8 +2181,6 @@ def provision(logger, session_info, smbconf=None, # Make a new, random password between Samba and it's LDAP server ldapadminpass = samba.generate_random_password(128, 255) - if backend_type is None: - backend_type = "ldb" if backend_store is None: backend_store = get_default_backend_store() @@ -2288,28 +2282,9 @@ def provision(logger, session_info, smbconf=None, schema = Schema(domainsid, invocationid=invocationid, schemadn=names.schemadn, base_schema=base_schema) - if backend_type == "ldb": - provision_backend = LDBBackend(backend_type, paths=paths, - lp=lp, - names=names, logger=logger) - elif backend_type == "fedora-ds": - provision_backend = FDSBackend(backend_type, paths=paths, - lp=lp, - names=names, logger=logger, domainsid=domainsid, - schema=schema, hostname=hostname, ldapadminpass=ldapadminpass, - slapd_path=slapd_path, - root=root) - elif backend_type == "openldap": - provision_backend = OpenLDAPBackend(backend_type, paths=paths, - lp=lp, - names=names, logger=logger, domainsid=domainsid, - schema=schema, hostname=hostname, ldapadminpass=ldapadminpass, - slapd_path=slapd_path, ol_mmr_urls=ol_mmr_urls, - ldap_backend_extra_port=ldap_backend_extra_port, - ldap_dryrun_mode=ldap_dryrun_mode, nosync=nosync, - ldap_backend_forced_uri=ldap_backend_forced_uri) - else: - raise ValueError("Unknown LDAP backend type selected") + provision_backend = LDBBackend(paths=paths, + lp=lp, + names=names, logger=logger) provision_backend.init() provision_backend.start() @@ -2480,8 +2455,7 @@ def provision_become_dc(smbconf=None, targetdir=None, adminpass=None, krbtgtpass=None, domainguid=None, policyguid=None, policyguid_dc=None, invocationid=None, machinepass=None, dnspass=None, dns_backend=None, root=None, nobody=None, users=None, - backup=None, serverrole=None, ldap_backend=None, - ldap_backend_type=None, sitename=None, debuglevel=1, use_ntvfs=False): + backup=None, serverrole=None, sitename=None, debuglevel=1, use_ntvfs=False): logger = logging.getLogger("provision") samba.set_debug_level(debuglevel) diff --git a/python/samba/provision/backend.py b/python/samba/provision/backend.py index dc06b131ae1..abf79db119d 100644 --- a/python/samba/provision/backend.py +++ b/python/samba/provision/backend.py @@ -25,30 +25,7 @@ """Functions for setting up a Samba configuration (LDB and LDAP backends).""" -from samba.compat import urllib_quote -import errno -import ldb -import os -import sys -import time import shutil -import subprocess - -from ldb import SCOPE_BASE, SCOPE_ONELEVEL, LdbError - -from samba import Ldb, read_and_sub_file, setup_file -from samba.credentials import Credentials, DONT_USE_KERBEROS -from samba.schema import Schema - - -class SlapdAlreadyRunning(Exception): - - def __init__(self, uri): - self.ldapi_uri = uri - super(SlapdAlreadyRunning, self).__init__("Another slapd Instance " - "seems already running on this host, listening to %s." % - self.ldapi_uri) - class BackendResult(object): @@ -59,27 +36,9 @@ class BackendResult(object): raise NotImplementedError(self.report_logger) -class LDAPBackendResult(BackendResult): - - def __init__(self, slapd_command_escaped, ldapdir): - self.slapd_command_escaped = slapd_command_escaped - self.ldapdir = ldapdir - - def report_logger(self, logger): - if self.slapd_command_escaped is not None: - # now display slapd_command_file.txt to show how slapd must be - # started next time - logger.info( - "Use later the following commandline to start slapd, then Samba:") - logger.info(self.slapd_command_escaped) - logger.info( - "This slapd-Commandline is also stored under: %s/ldap_backend_startup.sh", - self.ldapdir) - - class ProvisionBackend(object): - def __init__(self, backend_type, paths=None, lp=None, + def __init__(self, paths=None, lp=None, names=None, logger=None): """Provision a backend for samba4""" self.paths = paths @@ -88,10 +47,7 @@ class ProvisionBackend(object): self.names = names self.logger = logger - self.type = backend_type - - # Set a default - the code for "existing" below replaces this - self.ldap_backend_type = backend_type + self.type = "ldb" def init(self): """Initialize the backend.""" @@ -131,692 +87,3 @@ class LDBBackend(ProvisionBackend): pass -class LDAPBackend(ProvisionBackend): - - def __init__(self, backend_type, paths=None, lp=None, - names=None, logger=None, domainsid=None, - schema=None, hostname=None, ldapadminpass=None, - slapd_path=None, ldap_backend_extra_port=None, - ldap_backend_forced_uri=None, ldap_dryrun_mode=False): - - super(LDAPBackend, self).__init__(backend_type=backend_type, - paths=paths, lp=lp, - names=names, logger=logger) - - self.domainsid = domainsid - self.schema = schema - self.hostname = hostname - - self.ldapdir = os.path.join(paths.private_dir, "ldap") - self.ldapadminpass = ldapadminpass - - self.slapd_path = slapd_path - self.slapd_command = None - self.slapd_command_escaped = None - self.slapd_pid = os.path.join(self.ldapdir, "slapd.pid") - - self.ldap_backend_extra_port = ldap_backend_extra_port - self.ldap_dryrun_mode = ldap_dryrun_mode - - if ldap_backend_forced_uri is not None: - self.ldap_uri = ldap_backend_forced_uri - else: - self.ldap_uri = "ldapi://%s" % urllib_quote( - os.path.join(self.ldapdir, "ldapi"), safe="") - - if not os.path.exists(self.ldapdir): - os.mkdir(self.ldapdir) - - def init(self): - from samba.provision import ProvisioningError - # we will shortly start slapd with ldapi for final provisioning. first - # check with ldapsearch -> rootDSE via self.ldap_uri if another - # instance of slapd is already running - try: - ldapi_db = Ldb(self.ldap_uri) - ldapi_db.search(base="", scope=SCOPE_BASE, - expression="(objectClass=OpenLDAProotDSE)") - try: - f = open(self.slapd_pid, "r") - except IOError as err: - if err != errno.ENOENT: - raise - else: - try: - p = f.read() - finally: - f.close() - self.logger.info("Check for slapd process with PID: %s and terminate it manually." % p) - raise SlapdAlreadyRunning(self.ldap_uri) - except LdbError: - # XXX: We should never be catching all Ldb errors - pass - - # Try to print helpful messages when the user has not specified the - # path to slapd - if self.slapd_path is None: - raise ProvisioningError("Warning: LDAP-Backend must be setup with path to slapd, e.g. --slapd-path=\"/usr/local/libexec/slapd\"!") - if not os.path.exists(self.slapd_path): - self.logger.warning("Path (%s) to slapd does not exist!", - self.slapd_path) - - if not os.path.isdir(self.ldapdir): - os.makedirs(self.ldapdir, 0o700) - - # Put the LDIF of the schema into a database so we can search on - # it to generate schema-dependent configurations in Fedora DS and - # OpenLDAP - schemadb_path = os.path.join(self.ldapdir, "schema-tmp.ldb") - try: - os.unlink(schemadb_path) - except OSError: - pass - - self.schema.write_to_tmp_ldb(schemadb_path) - - self.credentials = Credentials() - self.credentials.guess(self.lp) - # Kerberos to an ldapi:// backend makes no sense (we also force EXTERNAL) - self.credentials.set_kerberos_state(DONT_USE_KERBEROS) - self.credentials.set_username("samba-admin") - self.credentials.set_password(self.ldapadminpass) - self.credentials.set_forced_sasl_mech("EXTERNAL") - - self.provision() - - def provision(self): - pass - - def start(self): - from samba.provision import ProvisioningError - self.slapd_command_escaped = "\'" + "\' \'".join(self.slapd_command) + "\'" - ldap_backend_script = os.path.join(self.ldapdir, "ldap_backend_startup.sh") - f = open(ldap_backend_script, 'w') - try: - f.write("#!/bin/sh\n" + self.slapd_command_escaped + " $@\n") - finally: - f.close() - - os.chmod(ldap_backend_script, 0o755) - - # Now start the slapd, so we can provision onto it. We keep the - # subprocess context around, to kill this off at the successful - # end of the script - self.slapd = subprocess.Popen(self.slapd_provision_command, - close_fds=True, shell=False) - - count = 0 - while self.slapd.poll() is None: - # Wait until the socket appears - try: - time.sleep(1) - ldapi_db = Ldb(self.ldap_uri, lp=self.lp, credentials=self.credentials) - ldapi_db.search(base="", scope=SCOPE_BASE, - expression="(objectClass=OpenLDAProotDSE)") - # If we have got here, then we must have a valid connection to - # the LDAP server! - return - except LdbError: - count = count + 1 - - if count > 15: - self.logger.error("Could not connect to slapd started with: %s" % "\'" + "\' \'".join(self.slapd_provision_command) + "\'") - raise ProvisioningError("slapd never accepted a connection within 15 seconds of starting") - - self.logger.error("Could not start slapd with: %s" % "\'" + "\' \'".join(self.slapd_provision_command) + "\'") - raise ProvisioningError("slapd died before we could make a connection to it") - - def shutdown(self): - # if an LDAP backend is in use, terminate slapd after final provision - # and check its proper termination - if self.slapd.poll() is None: - # Kill the slapd - if getattr(self.slapd, "terminate", None) is not None: - self.slapd.terminate() - else: - # Older python versions don't have .terminate() - import signal - os.kill(self.slapd.pid, signal.SIGTERM) - - # and now wait for it to die - self.slapd.communicate() - - def post_setup(self): - return LDAPBackendResult(self.slapd_command_escaped, - self.ldapdir) - - -class OpenLDAPBackend(LDAPBackend): - - def __init__(self, backend_type, paths=None, lp=None, - credentials=None, names=None, logger=None, domainsid=None, - schema=None, hostname=None, ldapadminpass=None, slapd_path=None, - ldap_backend_extra_port=None, ldap_dryrun_mode=False, - ol_mmr_urls=None, nosync=False, ldap_backend_forced_uri=None): - from samba.provision import setup_path - super(OpenLDAPBackend, self).__init__(backend_type=backend_type, - paths=paths, lp=lp, - names=names, logger=logger, - domainsid=domainsid, schema=schema, hostname=hostname, - ldapadminpass=ldapadminpass, slapd_path=slapd_path, - ldap_backend_extra_port=ldap_backend_extra_port, - ldap_backend_forced_uri=ldap_backend_forced_uri, - ldap_dryrun_mode=ldap_dryrun_mode) - - self.ol_mmr_urls = ol_mmr_urls - self.nosync = nosync - - self.slapdconf = os.path.join(self.ldapdir, "slapd.conf") - self.modulesconf = os.path.join(self.ldapdir, "modules.conf") - self.memberofconf = os.path.join(self.ldapdir, "memberof.conf") - self.olmmrserveridsconf = os.path.join(self.ldapdir, "mmr_serverids.conf") - self.olmmrsyncreplconf = os.path.join(self.ldapdir, "mmr_syncrepl.conf") - self.olcdir = os.path.join(self.ldapdir, "slapd.d") - self.olcseedldif = os.path.join(self.ldapdir, "olc_seed.ldif") - - self.schema = Schema(self.domainsid, - schemadn=self.names.schemadn, files=[ - setup_path("schema_samba4.ldif")]) - - def setup_db_dir(self, dbdir): - """Create a database directory. - - :param dbdir: Database directory. - """ - if not os.path.exists(dbdir): - os.makedirs(dbdir, 0o700) - - def provision(self): - from samba.provision import ProvisioningError, setup_path - # Wipe the directories so we can start - shutil.rmtree(os.path.join(self.ldapdir, "db"), True) - - # Allow the test scripts to turn off fsync() for OpenLDAP as for TDB - # and LDB - nosync_config = "" - if self.nosync: - nosync_config = "dbnosync" - - lnkattr = self.schema.linked_attributes() - refint_attributes = "" - memberof_config = "# Generated from Samba4 schema\n" - for att in lnkattr.keys(): - if lnkattr[att] is not None: - refint_attributes = refint_attributes + " " + att - - memberof_config += read_and_sub_file( - setup_path("memberof.conf"), { - "MEMBER_ATTR": att, - "MEMBEROF_ATTR": lnkattr[att]}) - - refint_config = read_and_sub_file( - setup_path("refint.conf"), {"LINK_ATTRS": refint_attributes}) - - attrs = ["linkID", "lDAPDisplayName"] - res = self.schema.ldb.search( - expression="(&(objectclass=attributeSchema)" - "(searchFlags:1.2.840.113556.1.4.803:=1))", - base=self.names.schemadn, scope=SCOPE_ONELEVEL, attrs=attrs) - index_config = "" - for i in range(0, len(res)): - index_attr = str(res[i]["lDAPDisplayName"][0]) - if index_attr == "objectGUID": - index_attr = "entryUUID" - - index_config += "index " + index_attr + " eq\n" - - # generate serverids, ldap-urls and syncrepl-blocks for mmr hosts - mmr_on_config = "" - mmr_replicator_acl = "" - mmr_serverids_config = "" - mmr_syncrepl_schema_config = "" - mmr_syncrepl_config_config = "" - mmr_syncrepl_domaindns_config = "" - mmr_syncrepl_forestdns_config = "" - mmr_syncrepl_user_config = "" - mmr_pass = "" - - if self.ol_mmr_urls is not None: - # For now, make these equal - mmr_pass = self.ldapadminpass - - url_list = list(filter(None, self.ol_mmr_urls.split(','))) - for url in url_list: - self.logger.info("Using LDAP-URL: " + url) - if len(url_list) == 1: - raise ProvisioningError("At least 2 LDAP-URLs needed for MMR!") - - mmr_on_config = "MirrorMode On" - mmr_replicator_acl = " by dn=cn=replicator,cn=samba read" - serverid = 0 - for url in url_list: - serverid = serverid + 1 - mmr_serverids_config += read_and_sub_file( - setup_path("mmr_serverids.conf"), { - "SERVERID": str(serverid), - "LDAPSERVER": url}) - rid = serverid * 10 - rid = rid + 1 - mmr_syncrepl_schema_config += read_and_sub_file( - setup_path("mmr_syncrepl.conf"), { - "RID": str(rid), - "MMRDN": self.names.schemadn, - "LDAPSERVER": url, - "MMR_PASSWORD": mmr_pass}) - - rid = rid + 1 - mmr_syncrepl_config_config += read_and_sub_file( - setup_path("mmr_syncrepl.conf"), { - "RID": str(rid), - "MMRDN": self.names.configdn, - "LDAPSERVER": url, - "MMR_PASSWORD": mmr_pass}) - - rid = rid + 1 - mmr_syncrepl_domaindns_config += read_and_sub_file( - setup_path("mmr_syncrepl.conf"), { - "RID": str(rid), - "MMRDN": "dc=DomainDNSZones," + self.names.domaindn, - "LDAPSERVER": url, - "MMR_PASSWORD": mmr_pass}) - - rid = rid + 1 - mmr_syncrepl_forestdns_config += read_and_sub_file( - setup_path("mmr_syncrepl.conf"), { - "RID": str(rid), - "MMRDN": "dc=ForestDNSZones," + self.names.domaindn, - "LDAPSERVER": url, - "MMR_PASSWORD": mmr_pass}) - - rid = rid + 1 - mmr_syncrepl_user_config += read_and_sub_file( - setup_path("mmr_syncrepl.conf"), { - "RID": str(rid), - "MMRDN": self.names.domaindn, - "LDAPSERVER": url, - "MMR_PASSWORD": mmr_pass}) - # OpenLDAP cn=config initialisation - olc_syncrepl_config = "" - olc_mmr_config = "" - # if mmr = yes, generate cn=config-replication directives - # and olc_seed.lif for the other mmr-servers - if self.ol_mmr_urls is not None: - serverid = 0 - olc_serverids_config = "" - olc_syncrepl_seed_config = "" - olc_mmr_config += read_and_sub_file( - setup_path("olc_mmr.conf"), {}) - rid = 500 - for url in url_list: - serverid = serverid + 1 - olc_serverids_config += read_and_sub_file( - setup_path("olc_serverid.conf"), { - "SERVERID": str(serverid), "LDAPSERVER": url}) - - rid = rid + 1 - olc_syncrepl_config += read_and_sub_file( - setup_path("olc_syncrepl.conf"), { - "RID": str(rid), "LDAPSERVER": url, - "MMR_PASSWORD": mmr_pass}) - - olc_syncrepl_seed_config += read_and_sub_file( - setup_path("olc_syncrepl_seed.conf"), { - "RID": str(rid), "LDAPSERVER": url}) - - setup_file(setup_path("olc_seed.ldif"), self.olcseedldif, - {"OLC_SERVER_ID_CONF": olc_serverids_config, - "OLC_PW": self.ldapadminpass, - "OLC_SYNCREPL_CONF": olc_syncrepl_seed_config}) - # end olc - - setup_file(setup_path("slapd.conf"), self.slapdconf, - {"DNSDOMAIN": self.names.dnsdomain, - "LDAPDIR": self.ldapdir, - "DOMAINDN": self.names.domaindn, - "CONFIGDN": self.names.configdn, - "SCHEMADN": self.names.schemadn, - "MEMBEROF_CONFIG": memberof_config, - "MIRRORMODE": mmr_on_config, - "REPLICATOR_ACL": mmr_replicator_acl, - "MMR_SERVERIDS_CONFIG": mmr_serverids_config, - "MMR_SYNCREPL_SCHEMA_CONFIG": mmr_syncrepl_schema_config, - "MMR_SYNCREPL_CONFIG_CONFIG": mmr_syncrepl_config_config, - "MMR_SYNCREPL_DOMAINDNS_CONFIG": mmr_syncrepl_domaindns_config, - "MMR_SYNCREPL_FORESTDNS_CONFIG": mmr_syncrepl_forestdns_config, - "MMR_SYNCREPL_USER_CONFIG": mmr_syncrepl_user_config, - "OLC_SYNCREPL_CONFIG": olc_syncrepl_config, - "OLC_MMR_CONFIG": olc_mmr_config, - "REFINT_CONFIG": refint_config, - "INDEX_CONFIG": index_config, - "ADMIN_UID": str(os.getuid()), - "NOSYNC": nosync_config, }) - - self.setup_db_dir(os.path.join(self.ldapdir, "db", "forestdns")) - self.setup_db_dir(os.path.join(self.ldapdir, "db", "domaindns")) - self.setup_db_dir(os.path.join(self.ldapdir, "db", "user")) - self.setup_db_dir(os.path.join(self.ldapdir, "db", "config")) - self.setup_db_dir(os.path.join(self.ldapdir, "db", "schema")) - self.setup_db_dir(os.path.join(self.ldapdir, "db", "samba")) - - if self.ol_mmr_urls is not None: - mmr = "" - else: - mmr = "#" - - cn_samba = read_and_sub_file( - setup_path("cn=samba.ldif"), - {"LDAPADMINPASS": self.ldapadminpass, - "MMR_PASSWORD": mmr_pass, - "MMR": mmr}) - - mapping = "schema-map-openldap-2.3" - backend_schema = "backend-schema.schema" - - f = open(setup_path(mapping), 'r') - try: - backend_schema_data = self.schema.convert_to_openldap( - "openldap", f.read()) - finally: - f.close() - assert backend_schema_data is not None - f = open(os.path.join(self.ldapdir, backend_schema), 'w') - try: - f.write(backend_schema_data) - finally: - f.close() - - # now we generate the needed strings to start slapd automatically, - if self.ldap_backend_extra_port is not None: - # When we use MMR, we can't use 0.0.0.0 as it uses the name - # specified there as part of it's clue as to it's own name, - # and not to replicate to itself - if self.ol_mmr_urls is None: - server_port_string = "ldap://0.0.0.0:%d" % self.ldap_backend_extra_port - else: - server_port_string = "ldap://%s.%s:%d" % (self.names.hostname, - self.names.dnsdomain, - self.ldap_backend_extra_port) - else: - server_port_string = "" - - # Prepare the 'result' information - the commands to return in - # particular - self.slapd_provision_command = [self.slapd_path, "-F" + self.olcdir, - "-h"] - - # copy this command so we have two version, one with -d0 and only - # ldapi (or the forced ldap_uri), and one with all the listen commands - self.slapd_command = list(self.slapd_provision_command) - - self.slapd_provision_command.extend([self.ldap_uri, "-d0"]) - uris = self.ldap_uri - if server_port_string != "": - uris = uris + " " + server_port_string - - self.slapd_command.append(uris) - - # Wipe the old sam.ldb databases away - shutil.rmtree(self.olcdir, True) - os.makedirs(self.olcdir, 0o770) - - # If we were just looking for crashes up to this point, it's a - # good time to exit before we realise we don't have OpenLDAP on - # this system - if self.ldap_dryrun_mode: - sys.exit(0) - - slapd_cmd = [self.slapd_path, "-Ttest", "-n", "0", "-f", - self.slapdconf, "-F", self.olcdir] - retcode = subprocess.call(slapd_cmd, close_fds=True, shell=False) - - if retcode != 0: - self.logger.error("conversion from slapd.conf to cn=config failed slapd started with: %s" % "\'" + "\' \'".join(slapd_cmd) + "\'") - raise ProvisioningError("conversion from slapd.conf to cn=config failed") - - if not os.path.exists(os.path.join(self.olcdir, "cn=config.ldif")): - raise ProvisioningError("conversion from slapd.conf to cn=config failed") - - # Don't confuse the admin by leaving the slapd.conf around - os.remove(self.slapdconf) - - cn_samba_cmd = [self.slapd_path, "-Tadd", "-b", "cn=samba", "-F", self.olcdir] - p = subprocess.Popen(cn_samba_cmd, stdin=subprocess.PIPE, shell=False) - p.stdin.write(cn_samba) - p.communicate() - - -class FDSBackend(LDAPBackend): - - def __init__(self, backend_type, paths=None, lp=None, - names=None, logger=None, domainsid=None, - schema=None, hostname=None, ldapadminpass=None, - slapd_path=None, ldap_backend_extra_port=None, - ldap_backend_forced_uri=None, ldap_dryrun_mode=False, - root=None, setup_ds_path=None): - - from samba.provision import setup_path - - super(FDSBackend, self).__init__(backend_type=backend_type, - paths=paths, lp=lp, - names=names, logger=logger, - domainsid=domainsid, schema=schema, hostname=hostname, - ldapadminpass=ldapadminpass, slapd_path=slapd_path, - ldap_backend_extra_port=ldap_backend_extra_port, - ldap_backend_forced_uri=ldap_backend_forced_uri, - ldap_dryrun_mode=ldap_dryrun_mode) - - self.root = root - self.setup_ds_path = setup_ds_path - self.ldap_instance = self.names.netbiosname.lower() - - self.sambadn = "CN=Samba" - - self.fedoradsinf = os.path.join(self.ldapdir, "fedorads.inf") - self.partitions_ldif = os.path.join(self.ldapdir, - "fedorads-partitions.ldif") - self.sasl_ldif = os.path.join(self.ldapdir, "fedorads-sasl.ldif") - self.dna_ldif = os.path.join(self.ldapdir, "fedorads-dna.ldif") - self.pam_ldif = os.path.join(self.ldapdir, "fedorads-pam.ldif") - self.refint_ldif = os.path.join(self.ldapdir, "fedorads-refint.ldif") - self.linked_attrs_ldif = os.path.join(self.ldapdir, - "fedorads-linked-attributes.ldif") - self.index_ldif = os.path.join(self.ldapdir, "fedorads-index.ldif") - self.samba_ldif = os.path.join(self.ldapdir, "fedorads-samba.ldif") - - self.samba3_schema = setup_path( - "../../examples/LDAP/samba.schema") - self.samba3_ldif = os.path.join(self.ldapdir, "samba3.ldif") - - self.retcode = subprocess.call(["bin/oLschema2ldif", - "-I", self.samba3_schema, - "-O", self.samba3_ldif, - "-b", self.names.domaindn], - close_fds=True, shell=False) - - if self.retcode != 0: - raise Exception("Unable to convert Samba 3 schema.") - - self.schema = Schema( - self.domainsid, - schemadn=self.names.schemadn, - files=[setup_path("schema_samba4.ldif"), self.samba3_ldif], - additional_prefixmap=["1000:1.3.6.1.4.1.7165.2.1", - "1001:1.3.6.1.4.1.7165.2.2"]) - - def provision(self): - from samba.provision import ProvisioningError, setup_path - if self.ldap_backend_extra_port is not None: - serverport = "ServerPort=%d" % self.ldap_backend_extra_port - else: - serverport = "" - - setup_file(setup_path("fedorads.inf"), self.fedoradsinf, - {"ROOT": self.root, - "HOSTNAME": self.hostname, - "DNSDOMAIN": self.names.dnsdomain, - "LDAPDIR": self.ldapdir, - "DOMAINDN": self.names.domaindn, - "LDAP_INSTANCE": self.ldap_instance, - "LDAPMANAGERDN": self.names.ldapmanagerdn, - "LDAPMANAGERPASS": self.ldapadminpass, - "SERVERPORT": serverport}) - - setup_file(setup_path("fedorads-partitions.ldif"), - self.partitions_ldif, - {"CONFIGDN": self.names.configdn, - "SCHEMADN": self.names.schemadn, - "SAMBADN": self.sambadn, - }) - - setup_file(setup_path("fedorads-sasl.ldif"), self.sasl_ldif, - {"SAMBADN": self.sambadn, - }) - - setup_file(setup_path("fedorads-dna.ldif"), self.dna_ldif, - {"DOMAINDN": self.names.domaindn, - "SAMBADN": self.sambadn, - "DOMAINSID": str(self.domainsid), - }) - - setup_file(setup_path("fedorads-pam.ldif"), self.pam_ldif) - - lnkattr = self.schema.linked_attributes() - - f = open(setup_path("fedorads-refint-delete.ldif"), 'r') - try: - refint_config = f.read() - finally: - f.close() - memberof_config = "" - index_config = "" - argnum = 3 - - for attr in lnkattr.keys(): - if lnkattr[attr] is not None: - refint_config += read_and_sub_file( - setup_path("fedorads-refint-add.ldif"), - {"ARG_NUMBER": str(argnum), - "LINK_ATTR": attr}) - memberof_config += read_and_sub_file( - setup_path("fedorads-linked-attributes.ldif"), - {"MEMBER_ATTR": attr, - "MEMBEROF_ATTR": lnkattr[attr]}) - index_config += read_and_sub_file( - setup_path("fedorads-index.ldif"), {"ATTR": attr}) - argnum += 1 - - f = open(self.refint_ldif, 'w') - try: - f.write(refint_config) - finally: - f.close() - f = open(self.linked_attrs_ldif, 'w') - try: - f.write(memberof_config) - finally: - f.close() - - attrs = ["lDAPDisplayName"] - res = self.schema.ldb.search( - expression="(&(objectclass=attributeSchema)" - "(searchFlags:1.2.840.113556.1.4.803:=1))", - base=self.names.schemadn, scope=SCOPE_ONELEVEL, attrs=attrs) - - for i in range(0, len(res)): - attr = str(res[i]["lDAPDisplayName"][0]) - - if attr == "objectGUID": - attr = "nsUniqueId" - - index_config += read_and_sub_file( - setup_path("fedorads-index.ldif"), {"ATTR": attr}) - - f = open(self.index_ldif, 'w') - try: - f.write(index_config) - finally: - f.close() - - setup_file(setup_path("fedorads-samba.ldif"), self.samba_ldif, { - "SAMBADN": self.sambadn, - "LDAPADMINPASS": self.ldapadminpass - }) - - mapping = "schema-map-fedora-ds-1.0" - backend_schema = "99_ad.ldif" - - # Build a schema file in Fedora DS format - f = open(setup_path(mapping), 'r') - try: - backend_schema_data = self.schema.convert_to_openldap("fedora-ds", - f.read()) - finally: - f.close() - assert backend_schema_data is not None - f = open(os.path.join(self.ldapdir, backend_schema), 'w') - try: - f.write(backend_schema_data) - finally: - f.close() - - self.credentials.set_bind_dn(self.names.ldapmanagerdn) - - # Destory the target directory, or else setup-ds.pl will complain - fedora_ds_dir = \ - os.path.join(self.ldapdir, - "slapd-" + self.ldap_instance) - shutil.rmtree(fedora_ds_dir, True) - - self.slapd_provision_command = [self.slapd_path, "-D", fedora_ds_dir, - "-i", self.slapd_pid] - # In the 'provision' command line, stay in the foreground so we can - # easily kill it - self.slapd_provision_command.append("-d0") - - # the command for the final run is the normal script - self.slapd_command = \ - [os.path.join(self.ldapdir, - "slapd-" + self.ldap_instance, "start-slapd")] - - # If we were just looking for crashes up to this point, it's a - # good time to exit before we realise we don't have Fedora DS on - if self.ldap_dryrun_mode: - sys.exit(0) - - # Try to print helpful messages when the user has not specified the - # path to the setup-ds tool - if self.setup_ds_path is None: - raise ProvisioningError("Fedora DS LDAP-Backend must be setup with path to setup-ds, e.g. --setup-ds-path=\"/usr/sbin/setup-ds.pl\"!") - if not os.path.exists(self.setup_ds_path): - self.logger.warning("Path (%s) to slapd does not exist!", - self.setup_ds_path) - - # Run the Fedora DS setup utility - retcode = subprocess.call([self.setup_ds_path, "--silent", "--file", - self.fedoradsinf], close_fds=True, shell=False) - if retcode != 0: - raise ProvisioningError("setup-ds failed") - - # Load samba-admin - retcode = subprocess.call([ - os.path.join(self.ldapdir, "slapd-" + self.ldap_instance, "ldif2db"), "-s", self.sambadn, "-i", self.samba_ldif], - close_fds=True, shell=False) - if retcode != 0: - raise ProvisioningError("ldif2db failed") - - def post_setup(self): - ldapi_db = Ldb(self.ldap_uri, credentials=self.credentials) - - # configure in-directory access control on Fedora DS via the aci - # attribute (over a direct ldapi:// socket) - aci = """(targetattr = "*") (version 3.0;acl "full access to all by samba-admin";allow (all)(userdn = "ldap:///CN=samba-admin,%s");)""" % self.sambadn - - m = ldb.Message() - m["aci"] = ldb.MessageElement([aci], ldb.FLAG_MOD_REPLACE, "aci") - - for dnstring in (self.names.domaindn, self.names.configdn, - self.names.schemadn): - m.dn = ldb.Dn(ldapi_db, dnstring) - ldapi_db.modify(m) - return LDAPBackendResult(self.slapd_command_escaped, - self.ldapdir) |