From 8caac9462ac09b7ff99a7032329d0e56c2e0aac5 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 28 Nov 2010 04:02:28 +0100 Subject: [PATCH] samba.provision: Add package with provision and backend modules. --- .../samba/{provision.py => provision/__init__.py} | 440 +++++++++++---------- .../{provisionbackend.py => provision/backend.py} | 207 +++++----- source4/scripting/python/samba/tests/samdb.py | 13 +- 3 files changed, 337 insertions(+), 323 deletions(-) rename source4/scripting/python/samba/{provision.py => provision/__init__.py} (84%) rename source4/scripting/python/samba/{provisionbackend.py => provision/backend.py} (88%) diff --git a/source4/scripting/python/samba/provision.py b/source4/scripting/python/samba/provision/__init__.py similarity index 84% rename from source4/scripting/python/samba/provision.py rename to source4/scripting/python/samba/provision/__init__.py index 70afc2a1ee8..1fed220507e 100644 --- a/source4/scripting/python/samba/provision.py +++ b/source4/scripting/python/samba/provision/__init__.py @@ -25,6 +25,8 @@ """Functions for setting up a Samba configuration.""" +__docformat__ = "restructuredText" + from base64 import b64encode import os import re @@ -62,7 +64,7 @@ from samba.idmap import IDmapDB from samba.ms_display_specifiers import read_ms_ldif from samba.ntacls import setntacl, dsacl2fsacl from samba.ndr import ndr_pack,ndr_unpack -from samba.provisionbackend import ( +from samba.provision.backend import ( ExistingBackend, FDSBackend, LDBBackend, @@ -74,9 +76,11 @@ from samba.schema import Schema from samba.samdb import SamDB VALID_NETBIOS_CHARS = " !#$%&'()-.@^_{}~" -__docformat__ = "restructuredText" DEFAULT_POLICY_GUID = "31B2F340-016D-11D2-945F-00C04FB984F9" DEFAULT_DC_POLICY_GUID = "6AC1786C-016F-11D2-945F-00C04fB984F9" +DEFAULTSITE = "Default-First-Site-Name" +LAST_PROVISION_USN_ATTRIBUTE = "lastProvisionUSN" + def find_setup_dir(): """Find the setup directory used by provision.""" @@ -112,6 +116,7 @@ def get_sites_descriptor(domain_sid): sec = security.descriptor.from_sddl(sddl, domain_sid) return ndr_pack(sec) + def get_config_descriptor(domain_sid): sddl = "O:EAG:EAD:(OA;;CR;1131f6aa-9c07-11d1-f79f-00c04fc2dcd2;;ED)" \ "(OA;;CR;1131f6ab-9c07-11d1-f79f-00c04fc2dcd2;;ED)" \ @@ -131,6 +136,7 @@ def get_config_descriptor(domain_sid): sec = security.descriptor.from_sddl(sddl, domain_sid) return ndr_pack(sec) + def get_domain_descriptor(domain_sid): 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)" \ @@ -184,8 +190,6 @@ def get_domain_descriptor(domain_sid): sec = security.descriptor.from_sddl(sddl, domain_sid) return ndr_pack(sec) -DEFAULTSITE = "Default-First-Site-Name" -LAST_PROVISION_USN_ATTRIBUTE = "lastProvisionUSN" class ProvisionPaths(object): @@ -252,8 +256,7 @@ def update_provision_usn(samdb, low, high, replace=False): delta = ldb.Message() delta.dn = ldb.Dn(samdb, "@PROVISION") delta[LAST_PROVISION_USN_ATTRIBUTE] = ldb.MessageElement(tab, - ldb.FLAG_MOD_REPLACE, - LAST_PROVISION_USN_ATTRIBUTE) + ldb.FLAG_MOD_REPLACE, LAST_PROVISION_USN_ATTRIBUTE) samdb.modify(delta) @@ -272,8 +275,7 @@ def set_provision_usn(samdb, low, high): delta = ldb.Message() delta.dn = ldb.Dn(samdb, "@PROVISION") delta[LAST_PROVISION_USN_ATTRIBUTE] = ldb.MessageElement(tab, - ldb.FLAG_MOD_ADD, - LAST_PROVISION_USN_ATTRIBUTE) + ldb.FLAG_MOD_ADD, LAST_PROVISION_USN_ATTRIBUTE) samdb.add(delta) @@ -292,6 +294,7 @@ def get_max_usn(samdb,basedn): "paged_results:1:1"]) return res[0]["uSNChanged"] + def get_last_provision_usn(sam): """Get the lastest USN modified by a provision or an upgradeprovision @@ -316,6 +319,7 @@ def get_last_provision_usn(sam): else: return None + class ProvisionResult(object): def __init__(self): @@ -384,7 +388,8 @@ def setup_modify_ldif(ldb, ldif_path, subst_vars=None,controls=["relax:0"]): def setup_ldb(ldb, ldif_path, subst_vars): - """Import a LDIF a file into a LDB handle, optionally substituting variables. + """Import a LDIF a file into a LDB handle, optionally substituting + variables. :note: Either all LDIF data will be added or none (using transactions). @@ -418,9 +423,12 @@ def provision_paths_from_lp(lp, dnsdomain): paths.keytab = "secrets.keytab" paths.shareconf = os.path.join(paths.private_dir, "share.ldb") - paths.samdb = os.path.join(paths.private_dir, lp.get("sam database") or "samdb.ldb") - paths.idmapdb = os.path.join(paths.private_dir, lp.get("idmap database") or "idmap.ldb") - paths.secrets = os.path.join(paths.private_dir, lp.get("secrets database") or "secrets.ldb") + paths.samdb = os.path.join(paths.private_dir, + lp.get("sam database") or "samdb.ldb") + paths.idmapdb = os.path.join(paths.private_dir, + lp.get("idmap database") or "idmap.ldb") + paths.secrets = os.path.join(paths.private_dir, + lp.get("secrets database") or "secrets.ldb") paths.privilege = os.path.join(paths.private_dir, "privilege.ldb") paths.dns = os.path.join(paths.private_dir, "dns", dnsdomain + ".zone") paths.dns_update_list = os.path.join(paths.private_dir, "dns_update_list") @@ -542,7 +550,8 @@ def guess_names(lp=None, hostname=None, domain=None, dnsdomain=None, names.netbiosname = netbiosname names.hostname = hostname names.sitename = sitename - names.serverdn = "CN=%s,CN=Servers,CN=%s,CN=Sites,%s" % (netbiosname, sitename, configdn) + names.serverdn = "CN=%s,CN=Servers,CN=%s,CN=Sites,%s" % ( + netbiosname, sitename, configdn) return names @@ -658,7 +667,8 @@ def setup_name_mappings(samdb, idmap, sid, domaindn, root_uid, nobody_uid, :param root_uid: uid of the UNIX root user. :param nobody_uid: uid of the UNIX nobody user. :param users_gid: gid of the UNIX users group. - :param wheel_gid: gid of the UNIX wheel group.""" + :param wheel_gid: gid of the UNIX wheel group. + """ idmap.setup_name_mapping("S-1-5-7", idmap.TYPE_UID, nobody_uid) idmap.setup_name_mapping("S-1-5-32-544", idmap.TYPE_GID, wheel_gid) @@ -733,7 +743,7 @@ def secretsdb_self_join(secretsdb, domain, :param secretsdb: Ldb Handle to the secrets database :param machinepass: Machine password """ - attrs=["whenChanged", + attrs = ["whenChanged", "secret", "priorSecret", "priorChanged", @@ -748,7 +758,8 @@ def secretsdb_self_join(secretsdb, domain, dnsname = None shortname = netbiosname.lower() - #We don't need to set msg["flatname"] here, because rdn_name will handle it, and it causes problems for modifies anyway + # We don't need to set msg["flatname"] here, because rdn_name will handle + # it, and it causes problems for modifies anyway msg = ldb.Message(ldb.Dn(secretsdb, "flatname=%s,cn=Primary Domains" % domain)) msg["secureChannelType"] = [str(secure_channel_type)] msg["objectClass"] = ["top", "primaryDomain"] @@ -780,38 +791,37 @@ def secretsdb_self_join(secretsdb, domain, res = secretsdb.search(base=msg.dn, attrs=attrs, scope=ldb.SCOPE_BASE) if len(res) == 1: - msg["priorSecret"] = [res[0]["secret"][0]] - msg["priorWhenChanged"] = [res[0]["whenChanged"][0]] + msg["priorSecret"] = [res[0]["secret"][0]] + msg["priorWhenChanged"] = [res[0]["whenChanged"][0]] - try: - msg["privateKeytab"] = [res[0]["privateKeytab"][0]] - except KeyError: - pass + try: + msg["privateKeytab"] = [res[0]["privateKeytab"][0]] + except KeyError: + pass - try: - msg["krb5Keytab"] = [res[0]["krb5Keytab"][0]] - except KeyError: - pass + try: + msg["krb5Keytab"] = [res[0]["krb5Keytab"][0]] + except KeyError: + pass - for el in msg: - if el != 'dn': - msg[el].set_flags(ldb.FLAG_MOD_REPLACE) - secretsdb.modify(msg) - secretsdb.rename(res[0].dn, msg.dn) + for el in msg: + if el != 'dn': + msg[el].set_flags(ldb.FLAG_MOD_REPLACE) + secretsdb.modify(msg) + secretsdb.rename(res[0].dn, msg.dn) else: - spn = [ 'HOST/%s' % shortname ] - if secure_channel_type == SEC_CHAN_BDC and dnsname is not None: - # we are a domain controller then we add servicePrincipalName entries - # for the keytab code to update - spn.extend([ 'HOST/%s' % dnsname ]) - msg["servicePrincipalName"] = spn + spn = [ 'HOST/%s' % shortname ] + if secure_channel_type == SEC_CHAN_BDC and dnsname is not None: + # we are a domain controller then we add servicePrincipalName + # entries for the keytab code to update. + spn.extend([ 'HOST/%s' % dnsname ]) + msg["servicePrincipalName"] = spn - secretsdb.add(msg) + secretsdb.add(msg) -def secretsdb_setup_dns(secretsdb, setup_path, names, private_dir, - realm, dnsdomain, - dns_keytab_path, dnspass): +def secretsdb_setup_dns(secretsdb, setup_path, names, private_dir, realm, + dnsdomain, dns_keytab_path, dnspass): """Add DNS specific bits to a secrets database. :param secretsdb: Ldb Handle to the secrets database @@ -829,7 +839,8 @@ def secretsdb_setup_dns(secretsdb, setup_path, names, private_dir, "DNS_KEYTAB": dns_keytab_path, "DNSPASS_B64": b64encode(dnspass), "HOSTNAME": names.hostname, - "DNSNAME" : '%s.%s' % (names.netbiosname.lower(), names.dnsdomain.lower()) + "DNSNAME" : '%s.%s' % ( + names.netbiosname.lower(), names.dnsdomain.lower()) }) @@ -869,14 +880,17 @@ def setup_secretsdb(paths, setup_path, session_info, backend_credentials, lp): try: secrets_ldb.load_ldif_file_add(setup_path("secrets.ldif")) - if backend_credentials is not None and backend_credentials.authentication_requested(): + if (backend_credentials is not None and + backend_credentials.authentication_requested()): if backend_credentials.get_bind_dn() is not None: - setup_add_ldif(secrets_ldb, setup_path("secrets_simple_ldap.ldif"), { + setup_add_ldif(secrets_ldb, + setup_path("secrets_simple_ldap.ldif"), { "LDAPMANAGERDN": backend_credentials.get_bind_dn(), "LDAPMANAGERPASS_B64": b64encode(backend_credentials.get_password()) }) else: - setup_add_ldif(secrets_ldb, setup_path("secrets_sasl_ldap.ldif"), { + setup_add_ldif(secrets_ldb, + setup_path("secrets_sasl_ldap.ldif"), { "LDAPADMINUSER": backend_credentials.get_username(), "LDAPADMINREALM": backend_credentials.get_realm(), "LDAPADMINPASS_B64": b64encode(backend_credentials.get_password()) @@ -887,6 +901,7 @@ def setup_secretsdb(paths, setup_path, session_info, backend_credentials, lp): secrets_ldb.transaction_cancel() raise + def setup_privileges(path, setup_path, session_info, lp): """Setup the privileges database. @@ -934,9 +949,7 @@ def setup_idmapdb(path, setup_path, session_info, lp): if os.path.exists(path): os.unlink(path) - idmap_ldb = IDmapDB(path, session_info=session_info, - lp=lp) - + idmap_ldb = IDmapDB(path, session_info=session_info, lp=lp) idmap_ldb.erase() idmap_ldb.load_ldif_file_add(setup_path("idmap_init.ldif")) return idmap_ldb @@ -981,7 +994,8 @@ def setup_self_join(samdb, names, "DCRID": str(next_rid), "SAMBA_VERSION_STRING": version, "NTDSGUID": ntdsguid_line, - "DOMAIN_CONTROLLER_FUNCTIONALITY": str(domainControllerFunctionality)}) + "DOMAIN_CONTROLLER_FUNCTIONALITY": str( + domainControllerFunctionality)}) setup_add_ldif(samdb, setup_path("provision_group_policy.ldif"), { "POLICYGUID": policyguid, @@ -1014,9 +1028,11 @@ def setup_self_join(samdb, names, "DOMAINDN": names.domaindn, "DNSPASS_B64": b64encode(dnspass.encode('utf-16-le')), "HOSTNAME" : names.hostname, - "DNSNAME" : '%s.%s' % (names.netbiosname.lower(), names.dnsdomain.lower()) + "DNSNAME" : '%s.%s' % ( + names.netbiosname.lower(), names.dnsdomain.lower()) }) + def getpolicypath(sysvolpath, dnsdomain, guid): """Return the physical path of policy given its guid. @@ -1031,6 +1047,7 @@ def getpolicypath(sysvolpath, dnsdomain, guid): policy_path = os.path.join(sysvolpath, dnsdomain, "Policies", guid) return policy_path + def create_gpo_struct(policy_path): if not os.path.exists(policy_path): os.makedirs(policy_path, 0775) @@ -1047,12 +1064,11 @@ def create_gpo_struct(policy_path): def create_default_gpo(sysvolpath, dnsdomain, policyguid, policyguid_dc): """Create the default GPO for a domain - :param sysvolpath: Physical path for the sysvol folder - :param dnsdomain: DNS domain name of the AD domain - :param policyguid: GUID of the default domain policy - :param policyguid_dc: GUID of the default domain controler policy + :param sysvolpath: Physical path for the sysvol folder + :param dnsdomain: DNS domain name of the AD domain + :param policyguid: GUID of the default domain policy + :param policyguid_dc: GUID of the default domain controler policy """ - policy_path = getpolicypath(sysvolpath,dnsdomain,policyguid) create_gpo_struct(policy_path) @@ -1070,13 +1086,13 @@ def setup_samdb(path, setup_path, session_info, provision_backend, lp, names, :note: This will wipe the main SAM database file! """ - # 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. if next_rid < 1000 or next_rid > 1000000000: error = "You want to run SAMBA 4 with a next_rid of %u, " % (next_rid) - error += "the valid range is %u-%u. The default is %u." % (1000, 1000000000, 1000) + error += "the valid range is %u-%u. The default is %u." % ( + 1000, 1000000000, 1000) raise ProvisioningError(error) # ATTENTION: Do NOT change these default values without discussion with the @@ -1100,10 +1116,11 @@ def setup_samdb(path, setup_path, session_info, provision_backend, lp, names, if schema is None: schema = Schema(setup_path, domainsid, schemadn=names.schemadn) - # Load the database, but don's load the global schema and don't connect quite yet + # Load the database, but don's load the global schema and don't connect + # quite yet samdb = SamDB(session_info=session_info, url=None, auto_connect=False, - credentials=provision_backend.credentials, lp=lp, global_schema=False, - am_rodc=am_rodc) + credentials=provision_backend.credentials, lp=lp, + global_schema=False, am_rodc=am_rodc) logger.info("Pre-loading the Samba 4 and AD schema") @@ -1114,7 +1131,8 @@ def setup_samdb(path, setup_path, session_info, provision_backend, lp, names, # before the provisioned tree exists and we connect samdb.set_ntds_settings_dn("CN=NTDS Settings,%s" % names.serverdn) - # And now we can connect to the DB - the schema won't be loaded from the DB + # And now we can connect to the DB - the schema won't be loaded from the + # DB samdb.connect(path) if fill == FILL_DRS: @@ -1130,14 +1148,15 @@ def setup_samdb(path, setup_path, session_info, provision_backend, lp, names, # modifictions below, but we need them set from the start. samdb.set_opaque_integer("domainFunctionality", domainFunctionality) samdb.set_opaque_integer("forestFunctionality", forestFunctionality) - samdb.set_opaque_integer("domainControllerFunctionality", domainControllerFunctionality) + samdb.set_opaque_integer("domainControllerFunctionality", + domainControllerFunctionality) samdb.set_domain_sid(str(domainsid)) samdb.set_invocation_id(invocationid) logger.info("Adding DomainDN: %s" % names.domaindn) -#impersonate domain admin + # impersonate domain admin admin_session_info = admin_session(lp, str(domainsid)) samdb.set_session_info(admin_session_info) if domainguid is not None: @@ -1194,7 +1213,6 @@ def setup_samdb(path, setup_path, session_info, provision_backend, lp, names, # Set the NTDS settings DN manually - in order to have it already around # before the provisioned tree exists and we connect samdb.set_ntds_settings_dn("CN=NTDS Settings,%s" % names.serverdn) - samdb.connect(path) samdb.transaction_start() @@ -1218,8 +1236,10 @@ def setup_samdb(path, setup_path, session_info, provision_backend, lp, names, }) logger.info("Setting up display specifiers") - display_specifiers_ldif = read_ms_ldif(setup_path('display-specifiers/DisplaySpecifiers-Win2k8R2.txt')) - display_specifiers_ldif = substitute_var(display_specifiers_ldif, {"CONFIGDN": names.configdn}) + display_specifiers_ldif = read_ms_ldif( + setup_path('display-specifiers/DisplaySpecifiers-Win2k8R2.txt')) + display_specifiers_ldif = substitute_var(display_specifiers_ldif, + {"CONFIGDN": names.configdn}) check_all_substituted(display_specifiers_ldif) samdb.add_ldif(display_specifiers_ldif) @@ -1233,7 +1253,8 @@ def setup_samdb(path, setup_path, session_info, provision_backend, lp, names, setup_add_ldif(samdb, setup_path("provision_computers_add.ldif"), { "DOMAINDN": names.domaindn}) logger.info("Modifying computers container") - setup_modify_ldif(samdb, setup_path("provision_computers_modify.ldif"), { + setup_modify_ldif(samdb, + setup_path("provision_computers_modify.ldif"), { "DOMAINDN": names.domaindn}) logger.info("Setting up sam.ldb data") setup_add_ldif(samdb, setup_path("provision.ldif"), { @@ -1247,10 +1268,12 @@ def setup_samdb(path, setup_path, session_info, provision_backend, lp, names, "POLICYGUID_DC": policyguid_dc }) - setup_modify_ldif(samdb, setup_path("provision_basedn_references.ldif"), { + setup_modify_ldif(samdb, + setup_path("provision_basedn_references.ldif"), { "DOMAINDN": names.domaindn}) - setup_modify_ldif(samdb, setup_path("provision_configuration_references.ldif"), { + setup_modify_ldif(samdb, + setup_path("provision_configuration_references.ldif"), { "CONFIGDN": names.configdn, "SCHEMADN": names.schemadn}) if fill == FILL_FULL: @@ -1265,15 +1288,15 @@ def setup_samdb(path, setup_path, session_info, provision_backend, lp, names, 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, - setup_path=setup_path, - domainControllerFunctionality=domainControllerFunctionality, - ntdsguid=ntdsguid) + dnspass=dnspass, + machinepass=machinepass, + domainsid=domainsid, + next_rid=next_rid, + policyguid=policyguid, + policyguid_dc=policyguid_dc, + setup_path=setup_path, + domainControllerFunctionality=domainControllerFunctionality, + ntdsguid=ntdsguid) ntds_dn = "CN=NTDS Settings,%s" % names.serverdn names.ntdsguid = samdb.searchone(basedn=ntds_dn, @@ -1329,6 +1352,7 @@ def set_gpos_acl(sysvol, dnsdomain, domainsid, domaindn, samdb, lp): set_dir_acl(policy_path, dsacl2fsacl(acl, str(domainsid)), lp, str(domainsid)) + def setsysvolacl(samdb, netlogon, sysvol, gid, domainsid, dnsdomain, domaindn, lp): """Set the ACL for the sysvol share and the subfolders @@ -1343,7 +1367,7 @@ def setsysvolacl(samdb, netlogon, sysvol, gid, domainsid, dnsdomain, domaindn, """ try: - os.chown(sysvol,-1,gid) + os.chown(sysvol, -1, gid) except: canchown = False else: @@ -1365,38 +1389,31 @@ def setsysvolacl(samdb, netlogon, sysvol, gid, domainsid, dnsdomain, domaindn, set_gpos_acl(sysvol, dnsdomain, domainsid, domaindn, samdb, lp) -def provision(setup_dir, logger, session_info, - credentials, smbconf=None, 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, 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, serverrole=None, - dom_for_fun_level=None, - ldap_backend_extra_port=None, ldap_backend_forced_uri=None, backend_type=None, - sitename=None, - ol_mmr_urls=None, ol_olc=None, - setup_ds_path=None, slapd_path=None, nosync=False, - ldap_dryrun_mode=False, useeadb=False, am_rodc=False, - lp=None): +def provision(setup_dir, logger, session_info, credentials, smbconf=None, + 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, + 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, + serverrole=None, dom_for_fun_level=None, ldap_backend_extra_port=None, + ldap_backend_forced_uri=None, backend_type=None, sitename=None, + ol_mmr_urls=None, ol_olc=None, setup_ds_path=None, slapd_path=None, + nosync=False, ldap_dryrun_mode=False, useeadb=False, am_rodc=False, + lp=None): """Provision samba4 :note: caution, this wipes all existing data! """ def setup_path(file): - return os.path.join(setup_dir, file) + return os.path.join(setup_dir, file) if domainsid is None: - domainsid = security.random_sid() + domainsid = security.random_sid() else: - domainsid = security.dom_sid(domainsid) + domainsid = security.dom_sid(domainsid) # create/adapt the group policy GUIDs # Default GUID for default policy are described at @@ -1418,7 +1435,7 @@ def provision(setup_dir, logger, session_info, if dnspass is None: dnspass = samba.generate_random_password(128, 255) if ldapadminpass is None: - #Make a new, random password between Samba and it's LDAP server + # Make a new, random password between Samba and it's LDAP server ldapadminpass=samba.generate_random_password(128, 255) if backend_type is None: @@ -1466,9 +1483,9 @@ def provision(setup_dir, logger, session_info, lp = samba.param.LoadParm() lp.load(smbconf) names = guess_names(lp=lp, hostname=hostname, domain=domain, - dnsdomain=realm, serverrole=serverrole, - domaindn=domaindn, configdn=configdn, schemadn=schemadn, - serverdn=serverdn, sitename=sitename) + dnsdomain=realm, serverrole=serverrole, domaindn=domaindn, + configdn=configdn, schemadn=schemadn, serverdn=serverdn, + sitename=sitename) paths = provision_paths_from_lp(lp, names.dnsdomain) paths.bind_gid = bind_gid @@ -1482,7 +1499,8 @@ def provision(setup_dir, logger, session_info, else: hostip = hostips[0] if len(hostips) > 1: - logger.warning("More than one IPv4 address found. Using %s.", hostip) + logger.warning("More than one IPv4 address found. Using %s.", + hostip) if serverrole is None: serverrole = lp.get("server role") @@ -1498,53 +1516,38 @@ def provision(setup_dir, logger, session_info, ldapi_url = "ldapi://%s" % urllib.quote(paths.s4_ldapi_path, safe="") - schema = Schema(setup_path, domainsid, invocationid=invocationid, schemadn=names.schemadn) + schema = Schema(setup_path, domainsid, invocationid=invocationid, + schemadn=names.schemadn) if backend_type == "ldb": - provision_backend = LDBBackend(backend_type, - paths=paths, setup_path=setup_path, - lp=lp, credentials=credentials, - names=names, - logger=logger) + provision_backend = LDBBackend(backend_type, paths=paths, + setup_path=setup_path, lp=lp, credentials=credentials, + names=names, logger=logger) elif backend_type == "existing": - provision_backend = ExistingBackend(backend_type, - paths=paths, setup_path=setup_path, - lp=lp, credentials=credentials, - names=names, - logger=logger, - ldap_backend_forced_uri=ldap_backend_forced_uri) + provision_backend = ExistingBackend(backend_type, paths=paths, + setup_path=setup_path, lp=lp, credentials=credentials, + names=names, logger=logger, + ldap_backend_forced_uri=ldap_backend_forced_uri) elif backend_type == "fedora-ds": - provision_backend = FDSBackend(backend_type, - paths=paths, setup_path=setup_path, - lp=lp, credentials=credentials, - 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_dryrun_mode=ldap_dryrun_mode, - root=root, - setup_ds_path=setup_ds_path, - ldap_backend_forced_uri=ldap_backend_forced_uri) + provision_backend = FDSBackend(backend_type, paths=paths, + setup_path=setup_path, lp=lp, credentials=credentials, + 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_dryrun_mode=ldap_dryrun_mode, root=root, + setup_ds_path=setup_ds_path, + ldap_backend_forced_uri=ldap_backend_forced_uri) elif backend_type == "openldap": - provision_backend = OpenLDAPBackend(backend_type, - paths=paths, setup_path=setup_path, - lp=lp, credentials=credentials, - 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_dryrun_mode=ldap_dryrun_mode, - ol_mmr_urls=ol_mmr_urls, - nosync=nosync, - ldap_backend_forced_uri=ldap_backend_forced_uri) + provision_backend = OpenLDAPBackend(backend_type, paths=paths, + setup_path=setup_path, lp=lp, credentials=credentials, + 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_dryrun_mode=ldap_dryrun_mode, ol_mmr_urls=ol_mmr_urls, + nosync=nosync, + ldap_backend_forced_uri=ldap_backend_forced_uri) else: raise ValueError("Unknown LDAP backend type selected") @@ -1572,23 +1575,19 @@ def provision(setup_dir, logger, session_info, setup_privileges(paths.privilege, setup_path, session_info, lp=lp) logger.info("Setting up idmap db") - idmap = setup_idmapdb(paths.idmapdb, setup_path, session_info=session_info, - lp=lp) + idmap = setup_idmapdb(paths.idmapdb, setup_path, + session_info=session_info, lp=lp) logger.info("Setting up SAM db") samdb = setup_samdb(paths.samdb, setup_path, session_info, - provision_backend, lp, names, - logger=logger, - domainsid=domainsid, - schema=schema, domainguid=domainguid, - policyguid=policyguid, policyguid_dc=policyguid_dc, - fill=samdb_fill, - adminpass=adminpass, krbtgtpass=krbtgtpass, - 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) + provision_backend, lp, names, logger=logger, + domainsid=domainsid, schema=schema, domainguid=domainguid, + policyguid=policyguid, policyguid_dc=policyguid_dc, + fill=samdb_fill, adminpass=adminpass, krbtgtpass=krbtgtpass, + 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) if serverrole == "domain controller": if paths.netlogon is None: @@ -1613,60 +1612,62 @@ def provision(setup_dir, logger, session_info, users_gid=users_gid, wheel_gid=wheel_gid) if serverrole == "domain controller": - # Set up group policies (domain policy and domain controller policy) - create_default_gpo(paths.sysvol, names.dnsdomain, policyguid, policyguid_dc) + # Set up group policies (domain policy and domain controller + # policy) + create_default_gpo(paths.sysvol, names.dnsdomain, policyguid, + policyguid_dc) setsysvolacl(samdb, paths.netlogon, paths.sysvol, wheel_gid, - domainsid, names.dnsdomain, names.domaindn, lp) + 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")) secretsdb_self_join(secrets_ldb, domain=names.domain, - realm=names.realm, - dnsdomain=names.dnsdomain, - netbiosname=names.netbiosname, - domainsid=domainsid, - machinepass=machinepass, - secure_channel_type=SEC_CHAN_BDC) + realm=names.realm, dnsdomain=names.dnsdomain, + netbiosname=names.netbiosname, domainsid=domainsid, + machinepass=machinepass, secure_channel_type=SEC_CHAN_BDC) # Now set up the right msDS-SupportedEncryptionTypes into the DB # In future, this might be determined from some configuration kerberos_enctypes = str(ENC_ALL_TYPES) try: - msg = ldb.Message(ldb.Dn(samdb, samdb.searchone("distinguishedName", expression="samAccountName=%s$" % names.netbiosname, scope=ldb.SCOPE_SUBTREE))) - msg["msDS-SupportedEncryptionTypes"] = ldb.MessageElement(elements=kerberos_enctypes, - flags=ldb.FLAG_MOD_REPLACE, - name="msDS-SupportedEncryptionTypes") + msg = ldb.Message(ldb.Dn(samdb, + samdb.searchone("distinguishedName", + expression="samAccountName=%s$" % names.netbiosname, + scope=ldb.SCOPE_SUBTREE))) + msg["msDS-SupportedEncryptionTypes"] = ldb.MessageElement( + elements=kerberos_enctypes, flags=ldb.FLAG_MOD_REPLACE, + name="msDS-SupportedEncryptionTypes") samdb.modify(msg) except ldb.LdbError, (ldb.ERR_NO_SUCH_ATTRIBUTE, _): # It might be that this attribute does not exist in this schema pass - if serverrole == "domain controller": secretsdb_setup_dns(secrets_ldb, setup_path, names, - paths.private_dir, - realm=names.realm, dnsdomain=names.dnsdomain, - dns_keytab_path=paths.dns_keytab, - dnspass=dnspass) + paths.private_dir, realm=names.realm, + dnsdomain=names.dnsdomain, + dns_keytab_path=paths.dns_keytab, dnspass=dnspass) - domainguid = samdb.searchone(basedn=domaindn, attribute="objectGUID") + domainguid = samdb.searchone(basedn=domaindn, + attribute="objectGUID") assert isinstance(domainguid, str) - # Only make a zone file on the first DC, it should be replicated - # with DNS replication + # Only make a zone file on the first DC, it should be + # replicated with DNS replication create_zone_file(lp, logger, paths, targetdir, setup_path, dnsdomain=names.dnsdomain, hostip=hostip, hostip6=hostip6, hostname=names.hostname, realm=names.realm, domainguid=domainguid, ntdsguid=names.ntdsguid) create_named_conf(paths, setup_path, realm=names.realm, - dnsdomain=names.dnsdomain, private_dir=paths.private_dir) + dnsdomain=names.dnsdomain, private_dir=paths.private_dir) - create_named_txt(paths.namedtxt, setup_path, realm=names.realm, - dnsdomain=names.dnsdomain, private_dir=paths.private_dir, - keytab_name=paths.dns_keytab) + create_named_txt(paths.namedtxt, setup_path, + realm=names.realm, dnsdomain=names.dnsdomain, + private_dir=paths.private_dir, + keytab_name=paths.dns_keytab) logger.info("See %s for an example configuration include file for BIND", paths.namedconf) logger.info("and %s for further documentation required for secure DNS " "updates", paths.namedtxt) @@ -1696,19 +1697,19 @@ def provision(setup_dir, logger, session_info, secrets_ldb.transaction_cancel() raise - #Now commit the secrets.ldb to disk + # Now commit the secrets.ldb to disk secrets_ldb.transaction_commit() # the commit creates the dns.keytab, now chown it dns_keytab_path = os.path.join(paths.private_dir, paths.dns_keytab) - if (os.path.isfile(dns_keytab_path) and paths.bind_gid is not None): + if os.path.isfile(dns_keytab_path) and paths.bind_gid is not None: try: os.chmod(dns_keytab_path, 0640) os.chown(dns_keytab_path, -1, paths.bind_gid) except OSError: if not os.environ.has_key('SAMBA_SELFTEST'): - logger.info("Failed to chown %s to bind gid %u", dns_keytab_path, - paths.bind_gid) + logger.info("Failed to chown %s to bind gid %u", + dns_keytab_path, paths.bind_gid) logger.info("Please install the phpLDAPadmin configuration located at %s into /etc/phpldapadmin/config.php", @@ -1724,14 +1725,18 @@ def provision(setup_dir, logger, session_info, logger.info("Admin password: %s" % adminpass) if provision_backend.type is not "ldb": if provision_backend.credentials.get_bind_dn() is not None: - logger.info("LDAP Backend Admin DN: %s" % provision_backend.credentials.get_bind_dn()) + logger.info("LDAP Backend Admin DN: %s" % + provision_backend.credentials.get_bind_dn()) else: - logger.info("LDAP Admin User: %s" % provision_backend.credentials.get_username()) + logger.info("LDAP Admin User: %s" % + provision_backend.credentials.get_username()) - logger.info("LDAP Admin Password: %s" % provision_backend.credentials.get_password()) + logger.info("LDAP Admin Password: %s" % + provision_backend.credentials.get_password()) if provision_backend.slapd_command_escaped is not None: - # now display slapd_command_file.txt to show how slapd must be started next time + # 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(provision_backend.slapd_command_escaped) logger.info("This slapd-Commandline is also stored under: %s/ldap_backend_startup.sh", @@ -1745,29 +1750,25 @@ def provision(setup_dir, logger, session_info, return result -def provision_become_dc(setup_dir=None, - smbconf=None, targetdir=None, realm=None, - rootdn=None, domaindn=None, schemadn=None, - configdn=None, serverdn=None, - domain=None, hostname=None, domainsid=None, - adminpass=None, krbtgtpass=None, domainguid=None, - policyguid=None, policyguid_dc=None, invocationid=None, - machinepass=None, - dnspass=None, root=None, nobody=None, users=None, - wheel=None, backup=None, serverrole=None, - ldap_backend=None, ldap_backend_type=None, - sitename=None, debuglevel=1): +def provision_become_dc(setup_dir=None, smbconf=None, targetdir=None, + realm=None, rootdn=None, domaindn=None, schemadn=None, configdn=None, + serverdn=None, domain=None, hostname=None, domainsid=None, + adminpass=None, krbtgtpass=None, domainguid=None, policyguid=None, + policyguid_dc=None, invocationid=None, machinepass=None, dnspass=None, + root=None, nobody=None, users=None, wheel=None, backup=None, + serverrole=None, ldap_backend=None, ldap_backend_type=None, + sitename=None, debuglevel=1): logger = logging.getLogger("provision") samba.set_debug_level(debuglevel) res = provision(setup_dir, logger, system_session(), None, - smbconf=smbconf, targetdir=targetdir, samdb_fill=FILL_DRS, - realm=realm, rootdn=rootdn, domaindn=domaindn, schemadn=schemadn, - configdn=configdn, serverdn=serverdn, domain=domain, - hostname=hostname, hostip="127.0.0.1", domainsid=domainsid, - machinepass=machinepass, serverrole="domain controller", - sitename=sitename) + smbconf=smbconf, targetdir=targetdir, samdb_fill=FILL_DRS, + realm=realm, rootdn=rootdn, domaindn=domaindn, schemadn=schemadn, + configdn=configdn, serverdn=serverdn, domain=domain, + hostname=hostname, hostip="127.0.0.1", domainsid=domainsid, + machinepass=machinepass, serverrole="domain controller", + sitename=sitename) res.lp.set("debuglevel", str(debuglevel)) return res @@ -1864,7 +1865,8 @@ def create_zone_file(lp, logger, paths, targetdir, setup_path, dnsdomain, os.chmod(paths.dns, 0664) except OSError: if not os.environ.has_key('SAMBA_SELFTEST'): - logger.error("Failed to chown %s to bind gid %u" % (dns_dir, paths.bind_gid)) + logger.error("Failed to chown %s to bind gid %u" % ( + dns_dir, paths.bind_gid)) if targetdir is None: os.system(rndc + " unfreeze " + lp.get("realm")) @@ -1903,8 +1905,8 @@ def create_named_conf(paths, setup_path, realm, dnsdomain, setup_file(setup_path("named.conf.update"), paths.namedconf_update) -def create_named_txt(path, setup_path, realm, dnsdomain, - private_dir, keytab_name): +def create_named_txt(path, setup_path, realm, dnsdomain, private_dir, + keytab_name): """Write out a file containing zone statements suitable for inclusion in a named.conf file (including GSS-TSIG configuration). @@ -1915,7 +1917,6 @@ def create_named_txt(path, setup_path, realm, dnsdomain, :param private_dir: Path to private directory :param keytab_name: File name of DNS keytab file """ - setup_file(setup_path("named.txt"), path, { "DNSDOMAIN": dnsdomain, "REALM": realm, @@ -1955,4 +1956,5 @@ class ProvisioningError(Exception): class InvalidNetbiosName(Exception): """A specified name was not a valid NetBIOS name.""" def __init__(self, name): - super(InvalidNetbiosName, self).__init__("The name '%r' is not a valid NetBIOS name" % name) + super(InvalidNetbiosName, self).__init__( + "The name '%r' is not a valid NetBIOS name" % name) diff --git a/source4/scripting/python/samba/provisionbackend.py b/source4/scripting/python/samba/provision/backend.py similarity index 88% rename from source4/scripting/python/samba/provisionbackend.py rename to source4/scripting/python/samba/provision/backend.py index 25563517c6b..32bcfeca954 100644 --- a/source4/scripting/python/samba/provisionbackend.py +++ b/source4/scripting/python/samba/provision/backend.py @@ -18,7 +18,7 @@ # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -# +# # You should have received a copy of the GNU General Public License # along with this program. If not, see . # @@ -65,7 +65,7 @@ class ProvisionBackend(object): self.logger = logger self.type = backend_type - + # Set a default - the code for "existing" below replaces this self.ldap_backend_type = backend_type @@ -91,7 +91,7 @@ class LDBBackend(ProvisionBackend): def init(self): self.credentials = None self.secrets_credentials = None - + # Wipe the old sam.ldb databases away shutil.rmtree(self.paths.samdb + ".d", True) @@ -160,7 +160,8 @@ class LDAPBackend(ProvisionBackend): 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="") + 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) @@ -169,7 +170,7 @@ class LDAPBackend(ProvisionBackend): 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 + # instance of slapd is already running try: ldapi_db = Ldb(self.ldap_uri) ldapi_db.search(base="", scope=SCOPE_BASE, @@ -182,7 +183,7 @@ class LDAPBackend(ProvisionBackend): else: p = f.read() f.close() - self.logger.info("Check for slapd Process with PID: " + str(p) + " and terminate it manually.") + 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 @@ -193,7 +194,8 @@ class LDAPBackend(ProvisionBackend): 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) + self.logger.warning("Path (%s) to slapd does not exist!", + self.slapd_path) if not os.path.isdir(self.ldapdir): os.makedirs(self.ldapdir, 0700) @@ -241,7 +243,7 @@ class LDAPBackend(ProvisionBackend): # 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 @@ -263,7 +265,8 @@ class LDAPBackend(ProvisionBackend): 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 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 hasattr(self.slapd, "terminate"): @@ -272,13 +275,14 @@ class LDAPBackend(ProvisionBackend): # 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): pass + class OpenLDAPBackend(LDAPBackend): def __init__(self, backend_type, paths=None, setup_path=None, lp=None, @@ -307,12 +311,12 @@ class OpenLDAPBackend(LDAPBackend): self.olcseedldif = os.path.join(self.ldapdir, "olc_seed.ldif") self.schema = Schema(self.setup_path, self.domainsid, - schemadn=self.names.schemadn, - files=[setup_path("schema_samba4.ldif")]) + schemadn=self.names.schemadn, files=[ + setup_path("schema_samba4.ldif")]) def setup_db_config(self, dbdir): """Setup a Berkeley database. - + :param setup_path: Setup path function. :param dbdir: Database directory.""" if not os.path.isdir(os.path.join(dbdir, "bdb-logs")): @@ -332,21 +336,22 @@ class OpenLDAPBackend(LDAPBackend): 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(self.setup_path("memberof.conf"), - { "MEMBER_ATTR" : att , - "MEMBEROF_ATTR" : lnkattr[att] }) - + refint_attributes = refint_attributes + " " + att + + memberof_config += read_and_sub_file( + self.setup_path("memberof.conf"), { + "MEMBER_ATTR": att, + "MEMBEROF_ATTR" : lnkattr[att] }) + refint_config = read_and_sub_file(self.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 = "" @@ -354,67 +359,67 @@ class OpenLDAPBackend(LDAPBackend): index_attr = 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_user_config = "" - + mmr_syncrepl_schema_config = "" + mmr_syncrepl_config_config = "" + mmr_syncrepl_user_config = "" + if self.ol_mmr_urls is not None: # For now, make these equal mmr_pass = self.ldapadminpass - - url_list=filter(None,self.ol_mmr_urls.split(',')) + + url_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): + 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 + serverid = 0 for url in url_list: - serverid=serverid+1 - mmr_serverids_config += read_and_sub_file(self.setup_path("mmr_serverids.conf"), - { "SERVERID" : str(serverid), - "LDAPSERVER" : url }) - rid=serverid*10 - rid=rid+1 - mmr_syncrepl_schema_config += read_and_sub_file( - self.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( - self.setup_path("mmr_syncrepl.conf"), { - "RID" : str(rid), - "MMRDN": self.names.configdn, - "LDAPSERVER" : url, - "MMR_PASSWORD": mmr_pass}) - - rid = rid+1 - mmr_syncrepl_user_config += read_and_sub_file( + serverid = serverid + 1 + mmr_serverids_config += read_and_sub_file( + self.setup_path("mmr_serverids.conf"), { + "SERVERID": str(serverid), + "LDAPSERVER": url }) + rid = serverid * 10 + rid = rid + 1 + mmr_syncrepl_schema_config += read_and_sub_file( self.setup_path("mmr_syncrepl.conf"), { "RID" : str(rid), - "MMRDN": self.names.domaindn, - "LDAPSERVER" : url, - "MMR_PASSWORD": mmr_pass }) + "MMRDN": self.names.schemadn, + "LDAPSERVER" : url, + "MMR_PASSWORD": mmr_pass}) + + rid = rid + 1 + mmr_syncrepl_config_config += read_and_sub_file( + self.setup_path("mmr_syncrepl.conf"), { + "RID" : str(rid), + "MMRDN": self.names.configdn, + "LDAPSERVER" : url, + "MMR_PASSWORD": mmr_pass}) + + rid = rid + 1 + mmr_syncrepl_user_config += read_and_sub_file( + self.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 = "" + 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 + serverid = 0 olc_serverids_config = "" olc_syncrepl_seed_config = "" olc_mmr_config += read_and_sub_file( @@ -425,23 +430,23 @@ class OpenLDAPBackend(LDAPBackend): olc_serverids_config += read_and_sub_file( self.setup_path("olc_serverid.conf"), { "SERVERID" : str(serverid), "LDAPSERVER" : url }) - + rid = rid + 1 olc_syncrepl_config += read_and_sub_file( self.setup_path("olc_syncrepl.conf"), { "RID" : str(rid), "LDAPSERVER" : url, "MMR_PASSWORD": mmr_pass}) - + olc_syncrepl_seed_config += read_and_sub_file( self.setup_path("olc_syncrepl_seed.conf"), { "RID" : str(rid), "LDAPSERVER" : url}) - + setup_file(self.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(self.setup_path("slapd.conf"), self.slapdconf, {"DNSDOMAIN": self.names.dnsdomain, "LDAPDIR": self.ldapdir, @@ -460,31 +465,30 @@ class OpenLDAPBackend(LDAPBackend): "REFINT_CONFIG": refint_config, "INDEX_CONFIG": index_config, "NOSYNC": nosync_config}) - + self.setup_db_config(os.path.join(self.ldapdir, "db", "user")) self.setup_db_config(os.path.join(self.ldapdir, "db", "config")) self.setup_db_config(os.path.join(self.ldapdir, "db", "schema")) if not os.path.exists(os.path.join(self.ldapdir, "db", "samba", "cn=samba")): os.makedirs(os.path.join(self.ldapdir, "db", "samba", "cn=samba"), 0700) - - setup_file(self.setup_path("cn=samba.ldif"), + + setup_file(self.setup_path("cn=samba.ldif"), os.path.join(self.ldapdir, "db", "samba", "cn=samba.ldif"), - { "UUID": str(uuid.uuid4()), + { "UUID": str(uuid.uuid4()), "LDAPTIME": timestring(int(time.time()))} ) - setup_file(self.setup_path("cn=samba-admin.ldif"), + setup_file(self.setup_path("cn=samba-admin.ldif"), os.path.join(self.ldapdir, "db", "samba", "cn=samba", "cn=samba-admin.ldif"), {"LDAPADMINPASS_B64": b64encode(self.ldapadminpass), - "UUID": str(uuid.uuid4()), + "UUID": str(uuid.uuid4()), "LDAPTIME": timestring(int(time.time()))} ) - + if self.ol_mmr_urls is not None: setup_file(self.setup_path("cn=replicator.ldif"), os.path.join(self.ldapdir, "db", "samba", "cn=samba", "cn=replicator.ldif"), {"MMR_PASSWORD_B64": b64encode(mmr_pass), "UUID": str(uuid.uuid4()), "LDAPTIME": timestring(int(time.time()))} ) - mapping = "schema-map-openldap-2.3" backend_schema = "backend-schema.schema" @@ -514,13 +518,13 @@ class OpenLDAPBackend(LDAPBackend): # Prepare the 'result' information - the commands to return in # particular - self.slapd_provision_command = [self.slapd_path, "-F" + self.olcdir, + 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 @@ -532,7 +536,7 @@ class OpenLDAPBackend(LDAPBackend): # Set the username - done here because Fedora DS still uses the admin # DN and simple bind self.credentials.set_username("samba-admin") - + # 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 @@ -543,9 +547,9 @@ class OpenLDAPBackend(LDAPBackend): if not os.path.isdir(self.olcdir): os.makedirs(self.olcdir, 0770) - slapd_cmd = [self.slapd_path, "-Ttest", "-n", "0", "-f", self.slapdconf, "-F", self.olcdir] - retcode = subprocess.call(slapd_cmd, close_fds=True, - shell=False) + 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) + "\'") @@ -555,7 +559,7 @@ class OpenLDAPBackend(LDAPBackend): 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) + os.remove(self.slapdconf) class FDSBackend(LDAPBackend): @@ -594,7 +598,7 @@ class FDSBackend(LDAPBackend): self.samba3_schema = self.setup_path("../../examples/LDAP/samba.schema") self.samba3_ldif = os.path.join(self.ldapdir, "samba3.ldif") - self.retcode = subprocess.call(["bin/oLschema2ldif", + self.retcode = subprocess.call(["bin/oLschema2ldif", "-I", self.samba3_schema, "-O", self.samba3_ldif, "-b", self.names.domaindn], @@ -608,7 +612,8 @@ class FDSBackend(LDAPBackend): 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"]) + 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 @@ -616,8 +621,8 @@ class FDSBackend(LDAPBackend): serverport = "ServerPort=%d" % self.ldap_backend_extra_port else: serverport = "" - - setup_file(self.setup_path("fedorads.inf"), self.fedoradsinf, + + setup_file(self.setup_path("fedorads.inf"), self.fedoradsinf, {"ROOT": self.root, "HOSTNAME": self.hostname, "DNSDOMAIN": self.names.dnsdomain, @@ -625,21 +630,21 @@ class FDSBackend(LDAPBackend): "DOMAINDN": self.names.domaindn, "LDAP_INSTANCE": self.ldap_instance, "LDAPMANAGERDN": self.names.ldapmanagerdn, - "LDAPMANAGERPASS": self.ldapadminpass, + "LDAPMANAGERPASS": self.ldapadminpass, "SERVERPORT": serverport}) setup_file(self.setup_path("fedorads-partitions.ldif"), - self.partitions_ldif, + self.partitions_ldif, {"CONFIGDN": self.names.configdn, "SCHEMADN": self.names.schemadn, "SAMBADN": self.sambadn, }) - setup_file(self.setup_path("fedorads-sasl.ldif"), self.sasl_ldif, + setup_file(self.setup_path("fedorads-sasl.ldif"), self.sasl_ldif, {"SAMBADN": self.sambadn, }) - setup_file(self.setup_path("fedorads-dna.ldif"), self.dna_ldif, + setup_file(self.setup_path("fedorads-dna.ldif"), self.dna_ldif, {"DOMAINDN": self.names.domaindn, "SAMBADN": self.sambadn, "DOMAINSID": str(self.domainsid), @@ -656,10 +661,12 @@ class FDSBackend(LDAPBackend): for attr in lnkattr.keys(): if lnkattr[attr] is not None: - refint_config += read_and_sub_file(self.setup_path("fedorads-refint-add.ldif"), + refint_config += read_and_sub_file( + self.setup_path("fedorads-refint-add.ldif"), { "ARG_NUMBER" : str(argnum), "LINK_ATTR" : attr }) - memberof_config += read_and_sub_file(self.setup_path("fedorads-linked-attributes.ldif"), + memberof_config += read_and_sub_file( + self.setup_path("fedorads-linked-attributes.ldif"), { "MEMBER_ATTR" : attr, "MEMBEROF_ATTR" : lnkattr[attr] }) index_config += read_and_sub_file( @@ -683,16 +690,17 @@ class FDSBackend(LDAPBackend): open(self.index_ldif, 'w').write(index_config) - setup_file(self.setup_path("fedorads-samba.ldif"), self.samba_ldif, - {"SAMBADN": self.sambadn, - "LDAPADMINPASS": self.ldapadminpass - }) + setup_file(self.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 - backend_schema_data = self.schema.convert_to_openldap("fedora-ds", open(self.setup_path(mapping), 'r').read()) + backend_schema_data = self.schema.convert_to_openldap("fedora-ds", + open(self.setup_path(mapping), 'r').read()) assert backend_schema_data is not None f = open(os.path.join(self.ldapdir, backend_schema), 'w') try: @@ -722,14 +730,17 @@ class FDSBackend(LDAPBackend): 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 + # 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) + 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) + retcode = subprocess.call([self.setup_ds_path, "--silent", "--file", + self.fedoradsinf], close_fds=True, shell=False) if retcode != 0: raise ProvisioningError("setup-ds failed") @@ -746,7 +757,7 @@ class FDSBackend(LDAPBackend): # 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") diff --git a/source4/scripting/python/samba/tests/samdb.py b/source4/scripting/python/samba/tests/samdb.py index f0a594dcf01..1536f163d12 100644 --- a/source4/scripting/python/samba/tests/samdb.py +++ b/source4/scripting/python/samba/tests/samdb.py @@ -2,17 +2,17 @@ # Unix SMB/CIFS implementation. Tests for SamDB # Copyright (C) Jelmer Vernooij 2008 -# +# # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. -# +# # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -# +# # You should have received a copy of the GNU General Public License # along with this program. If not, see . # @@ -21,9 +21,10 @@ import os import uuid from samba.auth import system_session -from samba.provision import setup_samdb, guess_names, make_smbconf, find_setup_dir, provision_paths_from_lp +from samba.provision import (setup_samdb, guess_names, make_smbconf, + find_setup_dir, provision_paths_from_lp) from samba.provision import DEFAULT_POLICY_GUID, DEFAULT_DC_POLICY_GUID -from samba.provisionbackend import ProvisionBackend +from samba.provision.backend import ProvisionBackend from samba.tests import TestCaseInTempDir from samba.dcerpc import security from samba.schema import Schema @@ -32,7 +33,7 @@ from samba import param class SamDBTestCase(TestCaseInTempDir): """Base-class for tests with a Sam Database. - + This is used by the Samba SamDB-tests, but e.g. also by the OpenChange provisioning tests (which need a Sam). """ -- 2.11.4.GIT