2 # Unix SMB/CIFS implementation.
3 # backend code for provisioning a Samba4 server
5 # Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007-2008
6 # Copyright (C) Andrew Bartlett <abartlet@samba.org> 2008
8 # Based on the original in EJS:
9 # Copyright (C) Andrew Tridgell <tridge@samba.org> 2005
11 # This program is free software; you can redistribute it and/or modify
12 # it under the terms of the GNU General Public License as published by
13 # the Free Software Foundation; either version 3 of the License, or
14 # (at your option) any later version.
16 # This program is distributed in the hope that it will be useful,
17 # but WITHOUT ANY WARRANTY; without even the implied warranty of
18 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 # GNU General Public License for more details.
21 # You should have received a copy of the GNU General Public License
22 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25 """Functions for setting up a Samba configuration."""
27 from base64 import b64encode
37 from auth import system_session
38 from samba import Ldb, substitute_var, valid_netbios_name, check_all_substituted
39 from samba.samdb import SamDB
40 from samba.idmap import IDmapDB
43 from ldb import SCOPE_SUBTREE, SCOPE_ONELEVEL, SCOPE_BASE, LdbError, \
44 LDB_ERR_NO_SUCH_OBJECT, timestring, CHANGETYPE_MODIFY, CHANGETYPE_NONE
46 __docformat__ = "restructuredText"
48 DEFAULTSITE = "Default-First-Site-Name"
50 class InvalidNetbiosName(Exception):
51 """A specified name was not a valid NetBIOS name."""
52 def __init__(self, name):
53 super(InvalidNetbiosName, self).__init__("The name '%r' is not a valid NetBIOS name" % name)
69 self.dns_keytab = None
72 self.private_dir = None
75 self.modulesconf = None
76 self.memberofconf = None
77 self.fedoradsinf = None
78 self.fedoradspartitions = None
86 self.ldapmanagerdn = None
89 self.netbiosname = None
95 class ProvisionResult:
102 def check_install(lp, session_info, credentials):
103 """Check whether the current install seems ok.
105 :param lp: Loadparm context
106 :param session_info: Session information
107 :param credentials: Credentials
109 if lp.get("realm") == "":
110 raise Exception("Realm empty")
111 ldb = Ldb(lp.get("sam database"), session_info=session_info,
112 credentials=credentials, lp=lp)
113 if len(ldb.search("(cn=Administrator)")) != 1:
114 raise "No administrator account found"
117 def findnss(nssfn, names):
118 """Find a user or group from a list of possibilities.
120 :param nssfn: NSS Function to try (should raise KeyError if not found)
121 :param names: Names to check.
122 :return: Value return by first names list.
129 raise KeyError("Unable to find user/group %r" % names)
132 findnss_uid = lambda names: findnss(pwd.getpwnam, names)[2]
133 findnss_gid = lambda names: findnss(grp.getgrnam, names)[2]
136 def open_ldb(session_info, credentials, lp, dbname):
137 """Open a LDB, thrashing it if it is corrupt.
139 :param session_info: auth session information
140 :param credentials: credentials
141 :param lp: Loadparm context
142 :param dbname: Path of the database to open.
143 :return: a Ldb object
145 assert session_info is not None
147 return Ldb(dbname, session_info=session_info, credentials=credentials,
152 return Ldb(dbname, session_info=session_info, credentials=credentials,
156 def read_and_sub_file(file, subst_vars):
157 """Read a file and sub in variables found in it
159 :param file: File to be read (typically from setup directory)
160 param subst_vars: Optional variables to subsitute in the file.
162 data = open(file, 'r').read()
163 if subst_vars is not None:
164 data = substitute_var(data, subst_vars)
165 check_all_substituted(data)
169 def setup_add_ldif(ldb, ldif_path, subst_vars=None):
170 """Setup a ldb in the private dir.
172 :param ldb: LDB file to import data into
173 :param ldif_path: Path of the LDIF file to load
174 :param subst_vars: Optional variables to subsitute in LDIF.
176 assert isinstance(ldif_path, str)
178 data = read_and_sub_file(ldif_path, subst_vars)
182 def setup_modify_ldif(ldb, ldif_path, subst_vars=None):
183 """Modify a ldb in the private dir.
185 :param ldb: LDB object.
186 :param ldif_path: LDIF file path.
187 :param subst_vars: Optional dictionary with substitution variables.
189 data = read_and_sub_file(ldif_path, subst_vars)
191 ldb.modify_ldif(data)
194 def setup_ldb(ldb, ldif_path, subst_vars):
195 """Import a LDIF a file into a LDB handle, optionally substituting variables.
197 :note: Either all LDIF data will be added or none (using transactions).
199 :param ldb: LDB file to import into.
200 :param ldif_path: Path to the LDIF file.
201 :param subst_vars: Dictionary with substitution variables.
203 assert ldb is not None
204 ldb.transaction_start()
206 setup_add_ldif(ldb, ldif_path, subst_vars)
208 ldb.transaction_cancel()
210 ldb.transaction_commit()
213 def setup_file(template, fname, subst_vars):
214 """Setup a file in the private dir.
216 :param template: Path of the template file.
217 :param fname: Path of the file to create.
218 :param subst_vars: Substitution variables.
222 if os.path.exists(f):
225 data = read_and_sub_file(template, subst_vars)
226 open(f, 'w').write(data)
229 def provision_paths_from_lp(lp, dnsdomain):
230 """Set the default paths for provisioning.
232 :param lp: Loadparm context.
233 :param dnsdomain: DNS Domain name
235 paths = ProvisionPaths()
236 paths.private_dir = lp.get("private dir")
237 paths.keytab = "secrets.keytab"
238 paths.dns_keytab = "dns.keytab"
240 paths.shareconf = os.path.join(paths.private_dir, "share.ldb")
241 paths.samdb = os.path.join(paths.private_dir, lp.get("sam database") or "samdb.ldb")
242 paths.idmapdb = os.path.join(paths.private_dir, lp.get("idmap database") or "idmap.ldb")
243 paths.secrets = os.path.join(paths.private_dir, lp.get("secrets database") or "secrets.ldb")
244 paths.templates = os.path.join(paths.private_dir, "templates.ldb")
245 paths.dns = os.path.join(paths.private_dir, dnsdomain + ".zone")
246 paths.namedconf = os.path.join(paths.private_dir, "named.conf")
247 paths.krb5conf = os.path.join(paths.private_dir, "krb5.conf")
248 paths.winsdb = os.path.join(paths.private_dir, "wins.ldb")
249 paths.s4_ldapi_path = os.path.join(paths.private_dir, "ldapi")
250 paths.phpldapadminconfig = os.path.join(paths.private_dir,
251 "phpldapadmin-config.php")
252 paths.ldapdir = os.path.join(paths.private_dir,
254 paths.slapdconf = os.path.join(paths.ldapdir,
256 paths.modulesconf = os.path.join(paths.ldapdir,
258 paths.memberofconf = os.path.join(paths.ldapdir,
260 paths.fedoradsinf = os.path.join(paths.ldapdir,
262 paths.fedoradspartitions = os.path.join(paths.ldapdir,
263 "fedorads-partitions.ldif")
264 paths.hklm = "hklm.ldb"
265 paths.hkcr = "hkcr.ldb"
266 paths.hkcu = "hkcu.ldb"
267 paths.hku = "hku.ldb"
268 paths.hkpd = "hkpd.ldb"
269 paths.hkpt = "hkpt.ldb"
271 paths.sysvol = lp.get("path", "sysvol")
273 paths.netlogon = lp.get("path", "netlogon")
275 paths.smbconf = lp.configfile()
280 def guess_names(lp=None, hostname=None, domain=None, dnsdomain=None, serverrole=None,
281 rootdn=None, domaindn=None, configdn=None, schemadn=None, serverdn=None,
283 """Guess configuration settings to use."""
286 hostname = socket.gethostname().split(".")[0].lower()
288 netbiosname = hostname.upper()
289 if not valid_netbios_name(netbiosname):
290 raise InvalidNetbiosName(netbiosname)
292 hostname = hostname.lower()
294 if dnsdomain is None:
295 dnsdomain = lp.get("realm")
297 if serverrole is None:
298 serverrole = lp.get("server role")
300 assert dnsdomain is not None
301 realm = dnsdomain.upper()
303 if lp.get("realm").upper() != realm:
304 raise Exception("realm '%s' in %s must match chosen realm '%s'" %
305 (lp.get("realm"), lp.configfile(), realm))
307 dnsdomain = dnsdomain.lower()
309 if serverrole == "domain controller":
311 domain = lp.get("workgroup")
313 domaindn = "DC=" + dnsdomain.replace(".", ",DC=")
314 if lp.get("workgroup").upper() != domain.upper():
315 raise Exception("workgroup '%s' in smb.conf must match chosen domain '%s'",
316 lp.get("workgroup"), domain)
320 domaindn = "CN=" + netbiosname
322 assert domain is not None
323 domain = domain.upper()
324 if not valid_netbios_name(domain):
325 raise InvalidNetbiosName(domain)
331 configdn = "CN=Configuration," + rootdn
333 schemadn = "CN=Schema," + configdn
338 names = ProvisionNames()
339 names.rootdn = rootdn
340 names.domaindn = domaindn
341 names.configdn = configdn
342 names.schemadn = schemadn
343 names.ldapmanagerdn = "CN=Manager," + rootdn
344 names.dnsdomain = dnsdomain
345 names.domain = domain
347 names.netbiosname = netbiosname
348 names.hostname = hostname
349 names.sitename = sitename
350 names.serverdn = "CN=%s,CN=Servers,CN=%s,CN=Sites,%s" % (netbiosname, sitename, configdn)
355 def make_smbconf(smbconf, setup_path, hostname, domain, realm, serverrole,
358 hostname = socket.gethostname().split(".")[0].lower()
360 if serverrole is None:
361 serverrole = "standalone"
363 assert serverrole in ("domain controller", "member server", "standalone")
364 if serverrole == "domain controller":
366 elif serverrole == "member server":
367 smbconfsuffix = "member"
368 elif serverrole == "standalone":
369 smbconfsuffix = "standalone"
371 assert domain is not None
372 assert realm is not None
374 default_lp = param.LoadParm()
375 #Load non-existant file
376 default_lp.load(smbconf)
378 if targetdir is not None:
379 privatedir_line = "private dir = " + os.path.abspath(os.path.join(targetdir, "private"))
380 lockdir_line = "lock dir = " + os.path.abspath(targetdir)
382 default_lp.set("lock dir", os.path.abspath(targetdir))
387 sysvol = os.path.join(default_lp.get("lock dir"), "sysvol")
388 netlogon = os.path.join(sysvol, realm.lower(), "scripts")
390 setup_file(setup_path("provision.smb.conf.%s" % smbconfsuffix),
392 "HOSTNAME": hostname,
395 "SERVERROLE": serverrole,
396 "NETLOGONPATH": netlogon,
397 "SYSVOLPATH": sysvol,
398 "PRIVATEDIR_LINE": privatedir_line,
399 "LOCKDIR_LINE": lockdir_line
404 def setup_name_mappings(samdb, idmap, sid, domaindn, root_uid, nobody_uid,
405 users_gid, wheel_gid):
406 """setup reasonable name mappings for sam names to unix names.
408 :param samdb: SamDB object.
409 :param idmap: IDmap db object.
410 :param sid: The domain sid.
411 :param domaindn: The domain DN.
412 :param root_uid: uid of the UNIX root user.
413 :param nobody_uid: uid of the UNIX nobody user.
414 :param users_gid: gid of the UNIX users group.
415 :param wheel_gid: gid of the UNIX wheel group."""
416 # add some foreign sids if they are not present already
417 samdb.add_foreign(domaindn, "S-1-5-7", "Anonymous")
418 samdb.add_foreign(domaindn, "S-1-1-0", "World")
419 samdb.add_foreign(domaindn, "S-1-5-2", "Network")
420 samdb.add_foreign(domaindn, "S-1-5-18", "System")
421 samdb.add_foreign(domaindn, "S-1-5-11", "Authenticated Users")
423 idmap.setup_name_mapping("S-1-5-7", idmap.TYPE_UID, nobody_uid)
424 idmap.setup_name_mapping("S-1-5-32-544", idmap.TYPE_GID, wheel_gid)
426 idmap.setup_name_mapping(sid + "-500", idmap.TYPE_UID, root_uid)
427 idmap.setup_name_mapping(sid + "-513", idmap.TYPE_GID, users_gid)
430 def setup_samdb_partitions(samdb_path, setup_path, message, lp, session_info,
432 serverrole, ldap_backend=None,
433 ldap_backend_type=None, erase=False):
434 """Setup the partitions for the SAM database.
436 Alternatively, provision() may call this, and then populate the database.
438 :note: This will wipe the Sam Database!
440 :note: This function always removes the local SAM LDB file. The erase
441 parameter controls whether to erase the existing data, which
442 may not be stored locally but in LDAP.
444 assert session_info is not None
446 samdb = SamDB(samdb_path, session_info=session_info,
447 credentials=credentials, lp=lp)
453 os.unlink(samdb_path)
455 samdb = SamDB(samdb_path, session_info=session_info,
456 credentials=credentials, lp=lp)
458 #Add modules to the list to activate them by default
459 #beware often order is important
461 # Some Known ordering constraints:
462 # - rootdse must be first, as it makes redirects from "" -> cn=rootdse
463 # - objectclass must be before password_hash, because password_hash checks
464 # that the objectclass is of type person (filled in by objectclass
465 # module when expanding the objectclass list)
466 # - partition must be last
467 # - each partition has its own module list then
468 modules_list = ["rootdse",
484 modules_list2 = ["show_deleted",
487 domaindn_ldb = "users.ldb"
488 if ldap_backend is not None:
489 domaindn_ldb = ldap_backend
490 configdn_ldb = "configuration.ldb"
491 if ldap_backend is not None:
492 configdn_ldb = ldap_backend
493 schemadn_ldb = "schema.ldb"
494 if ldap_backend is not None:
495 schema_ldb = ldap_backend
496 schemadn_ldb = ldap_backend
498 if ldap_backend_type == "fedora-ds":
499 backend_modules = ["nsuniqueid", "paged_searches"]
500 # We can handle linked attributes here, as we don't have directory-side subtree operations
501 tdb_modules_list = ["linked_attributes"]
502 elif ldap_backend_type == "openldap":
503 backend_modules = ["normalise", "entryuuid", "paged_searches"]
504 # OpenLDAP handles subtree renames, so we don't want to do any of these things
505 tdb_modules_list = None
506 elif ldap_backend is not None:
507 raise "LDAP Backend specified, but LDAP Backend Type not specified"
508 elif serverrole == "domain controller":
509 backend_modules = ["repl_meta_data"]
511 backend_modules = ["objectguid"]
513 if tdb_modules_list is None:
514 tdb_modules_list_as_string = ""
516 tdb_modules_list_as_string = ","+",".join(tdb_modules_list)
518 samdb.transaction_start()
520 setup_add_ldif(samdb, setup_path("provision_partitions.ldif"), {
521 "SCHEMADN": names.schemadn,
522 "SCHEMADN_LDB": schemadn_ldb,
523 "SCHEMADN_MOD2": ",objectguid",
524 "CONFIGDN": names.configdn,
525 "CONFIGDN_LDB": configdn_ldb,
526 "DOMAINDN": names.domaindn,
527 "DOMAINDN_LDB": domaindn_ldb,
528 "SCHEMADN_MOD": "schema_fsmo,instancetype",
529 "CONFIGDN_MOD": "naming_fsmo,instancetype",
530 "DOMAINDN_MOD": "pdc_fsmo,password_hash,instancetype",
531 "MODULES_LIST": ",".join(modules_list),
532 "TDB_MODULES_LIST": tdb_modules_list_as_string,
533 "MODULES_LIST2": ",".join(modules_list2),
534 "BACKEND_MOD": ",".join(backend_modules),
538 samdb.transaction_cancel()
541 samdb.transaction_commit()
543 samdb = SamDB(samdb_path, session_info=session_info,
544 credentials=credentials, lp=lp)
546 samdb.transaction_start()
548 message("Setting up sam.ldb attributes")
549 samdb.load_ldif_file_add(setup_path("provision_init.ldif"))
551 message("Setting up sam.ldb rootDSE")
552 setup_samdb_rootdse(samdb, setup_path, names)
555 message("Erasing data from partitions")
556 samdb.erase_partitions()
559 samdb.transaction_cancel()
562 samdb.transaction_commit()
567 def secretsdb_become_dc(secretsdb, setup_path, domain, realm, dnsdomain,
568 netbiosname, domainsid, keytab_path, samdb_url,
569 dns_keytab_path, dnspass, machinepass):
570 """Add DC-specific bits to a secrets database.
572 :param secretsdb: Ldb Handle to the secrets database
573 :param setup_path: Setup path function
574 :param machinepass: Machine password
576 setup_ldb(secretsdb, setup_path("secrets_dc.ldif"), {
577 "MACHINEPASS_B64": b64encode(machinepass),
580 "DNSDOMAIN": dnsdomain,
581 "DOMAINSID": str(domainsid),
582 "SECRETS_KEYTAB": keytab_path,
583 "NETBIOSNAME": netbiosname,
584 "SAM_LDB": samdb_url,
585 "DNS_KEYTAB": dns_keytab_path,
586 "DNSPASS_B64": b64encode(dnspass),
590 def setup_secretsdb(path, setup_path, session_info, credentials, lp):
591 """Setup the secrets database.
593 :param path: Path to the secrets database.
594 :param setup_path: Get the path to a setup file.
595 :param session_info: Session info.
596 :param credentials: Credentials
597 :param lp: Loadparm context
598 :return: LDB handle for the created secrets database
600 if os.path.exists(path):
602 secrets_ldb = Ldb(path, session_info=session_info, credentials=credentials,
605 secrets_ldb.load_ldif_file_add(setup_path("secrets_init.ldif"))
606 secrets_ldb = Ldb(path, session_info=session_info, credentials=credentials,
608 secrets_ldb.load_ldif_file_add(setup_path("secrets.ldif"))
610 if credentials is not None and credentials.authentication_requested():
611 if credentials.get_bind_dn() is not None:
612 setup_add_ldif(secrets_ldb, setup_path("secrets_simple_ldap.ldif"), {
613 "LDAPMANAGERDN": credentials.get_bind_dn(),
614 "LDAPMANAGERPASS_B64": b64encode(credentials.get_password())
617 setup_add_ldif(secrets_ldb, setup_path("secrets_sasl_ldap.ldif"), {
618 "LDAPADMINUSER": credentials.get_username(),
619 "LDAPADMINREALM": credentials.get_realm(),
620 "LDAPADMINPASS_B64": b64encode(credentials.get_password())
626 def setup_templatesdb(path, setup_path, session_info, credentials, lp):
627 """Setup the templates database.
629 :param path: Path to the database.
630 :param setup_path: Function for obtaining the path to setup files.
631 :param session_info: Session info
632 :param credentials: Credentials
633 :param lp: Loadparm context
635 templates_ldb = SamDB(path, session_info=session_info,
636 credentials=credentials, lp=lp)
637 templates_ldb.erase()
638 templates_ldb.load_ldif_file_add(setup_path("provision_templates.ldif"))
641 def setup_registry(path, setup_path, session_info, credentials, lp):
642 """Setup the registry.
644 :param path: Path to the registry database
645 :param setup_path: Function that returns the path to a setup.
646 :param session_info: Session information
647 :param credentials: Credentials
648 :param lp: Loadparm context
650 reg = registry.Registry()
651 hive = registry.open_ldb(path, session_info=session_info,
652 credentials=credentials, lp_ctx=lp)
653 reg.mount_hive(hive, "HKEY_LOCAL_MACHINE")
654 provision_reg = setup_path("provision.reg")
655 assert os.path.exists(provision_reg)
656 reg.diff_apply(provision_reg)
659 def setup_idmapdb(path, setup_path, session_info, credentials, lp):
660 """Setup the idmap database.
662 :param path: path to the idmap database
663 :param setup_path: Function that returns a path to a setup file
664 :param session_info: Session information
665 :param credentials: Credentials
666 :param lp: Loadparm context
668 if os.path.exists(path):
671 idmap_ldb = IDmapDB(path, session_info=session_info,
672 credentials=credentials, lp=lp)
675 idmap_ldb.load_ldif_file_add(setup_path("idmap_init.ldif"))
679 def setup_samdb_rootdse(samdb, setup_path, names):
680 """Setup the SamDB rootdse.
682 :param samdb: Sam Database handle
683 :param setup_path: Obtain setup path
685 setup_add_ldif(samdb, setup_path("provision_rootdse_add.ldif"), {
686 "SCHEMADN": names.schemadn,
687 "NETBIOSNAME": names.netbiosname,
688 "DNSDOMAIN": names.dnsdomain,
689 "REALM": names.realm,
690 "DNSNAME": "%s.%s" % (names.hostname, names.dnsdomain),
691 "DOMAINDN": names.domaindn,
692 "ROOTDN": names.rootdn,
693 "CONFIGDN": names.configdn,
694 "SERVERDN": names.serverdn,
698 def setup_self_join(samdb, names,
699 machinepass, dnspass,
700 domainsid, invocationid, setup_path,
702 """Join a host to its own domain."""
703 assert isinstance(invocationid, str)
704 setup_add_ldif(samdb, setup_path("provision_self_join.ldif"), {
705 "CONFIGDN": names.configdn,
706 "SCHEMADN": names.schemadn,
707 "DOMAINDN": names.domaindn,
708 "SERVERDN": names.serverdn,
709 "INVOCATIONID": invocationid,
710 "NETBIOSNAME": names.netbiosname,
711 "DEFAULTSITE": names.sitename,
712 "DNSNAME": "%s.%s" % (names.hostname, names.dnsdomain),
713 "MACHINEPASS_B64": b64encode(machinepass),
714 "DNSPASS_B64": b64encode(dnspass),
715 "REALM": names.realm,
716 "DOMAIN": names.domain,
717 "DNSDOMAIN": names.dnsdomain})
718 setup_add_ldif(samdb, setup_path("provision_group_policy.ldif"), {
719 "POLICYGUID": policyguid,
720 "DNSDOMAIN": names.dnsdomain,
721 "DOMAINSID": str(domainsid),
722 "DOMAINDN": names.domaindn})
725 def setup_samdb(path, setup_path, session_info, credentials, lp,
727 domainsid, aci, domainguid, policyguid,
728 fill, adminpass, krbtgtpass,
729 machinepass, invocationid, dnspass,
730 serverrole, ldap_backend=None,
731 ldap_backend_type=None):
732 """Setup a complete SAM Database.
734 :note: This will wipe the main SAM database file!
737 erase = (fill != FILL_DRS)
739 # Also wipes the database
740 setup_samdb_partitions(path, setup_path, message=message, lp=lp,
741 credentials=credentials, session_info=session_info,
743 ldap_backend=ldap_backend, serverrole=serverrole,
744 ldap_backend_type=ldap_backend_type, erase=erase)
746 samdb = SamDB(path, session_info=session_info,
747 credentials=credentials, lp=lp)
750 # We want to finish here, but setup the index before we do so
751 message("Setting up sam.ldb index")
752 samdb.load_ldif_file_add(setup_path("provision_index.ldif"))
755 message("Pre-loading the Samba 4 and AD schema")
756 samdb.set_domain_sid(domainsid)
757 if serverrole == "domain controller":
758 samdb.set_invocation_id(invocationid)
760 load_schema(setup_path, samdb, names.schemadn, names.netbiosname,
761 names.configdn, names.sitename)
763 samdb.transaction_start()
766 message("Adding DomainDN: %s (permitted to fail)" % names.domaindn)
767 if serverrole == "domain controller":
768 domain_oc = "domainDNS"
770 domain_oc = "samba4LocalDomain"
772 setup_add_ldif(samdb, setup_path("provision_basedn.ldif"), {
773 "DOMAINDN": names.domaindn,
775 "DOMAIN_OC": domain_oc
778 message("Modifying DomainDN: " + names.domaindn + "")
779 if domainguid is not None:
780 domainguid_mod = "replace: objectGUID\nobjectGUID: %s\n-" % domainguid
784 setup_modify_ldif(samdb, setup_path("provision_basedn_modify.ldif"), {
785 "LDAPTIME": timestring(int(time.time())),
786 "DOMAINSID": str(domainsid),
787 "SCHEMADN": names.schemadn,
788 "NETBIOSNAME": names.netbiosname,
789 "DEFAULTSITE": names.sitename,
790 "CONFIGDN": names.configdn,
791 "SERVERDN": names.serverdn,
792 "POLICYGUID": policyguid,
793 "DOMAINDN": names.domaindn,
794 "DOMAINGUID_MOD": domainguid_mod,
797 message("Adding configuration container (permitted to fail)")
798 setup_add_ldif(samdb, setup_path("provision_configuration_basedn.ldif"), {
799 "CONFIGDN": names.configdn,
801 "EXTENSIBLEOBJECT": "# no objectClass: extensibleObject for local ldb",
803 message("Modifying configuration container")
804 setup_modify_ldif(samdb, setup_path("provision_configuration_basedn_modify.ldif"), {
805 "CONFIGDN": names.configdn,
806 "SCHEMADN": names.schemadn,
809 message("Adding schema container (permitted to fail)")
810 setup_add_ldif(samdb, setup_path("provision_schema_basedn.ldif"), {
811 "SCHEMADN": names.schemadn,
813 "EXTENSIBLEOBJECT": "# no objectClass: extensibleObject for local ldb"
815 message("Modifying schema container")
817 prefixmap = open(setup_path("prefixMap.txt"), 'r').read()
819 setup_modify_ldif(samdb,
820 setup_path("provision_schema_basedn_modify.ldif"), {
821 "SCHEMADN": names.schemadn,
822 "NETBIOSNAME": names.netbiosname,
823 "DEFAULTSITE": names.sitename,
824 "CONFIGDN": names.configdn,
825 "SERVERDN": names.serverdn,
826 "PREFIXMAP_B64": b64encode(prefixmap)
829 message("Setting up sam.ldb Samba4 schema")
830 setup_add_ldif(samdb, setup_path("schema_samba4.ldif"),
831 {"SCHEMADN": names.schemadn })
832 message("Setting up sam.ldb AD schema")
833 setup_add_ldif(samdb, setup_path("schema.ldif"),
834 {"SCHEMADN": names.schemadn})
836 message("Setting up sam.ldb configuration data")
837 setup_add_ldif(samdb, setup_path("provision_configuration.ldif"), {
838 "CONFIGDN": names.configdn,
839 "NETBIOSNAME": names.netbiosname,
840 "DEFAULTSITE": names.sitename,
841 "DNSDOMAIN": names.dnsdomain,
842 "DOMAIN": names.domain,
843 "SCHEMADN": names.schemadn,
844 "DOMAINDN": names.domaindn,
845 "SERVERDN": names.serverdn
848 message("Setting up display specifiers")
849 setup_add_ldif(samdb, setup_path("display_specifiers.ldif"),
850 {"CONFIGDN": names.configdn})
852 message("Adding users container (permitted to fail)")
853 setup_add_ldif(samdb, setup_path("provision_users_add.ldif"), {
854 "DOMAINDN": names.domaindn})
855 message("Modifying users container")
856 setup_modify_ldif(samdb, setup_path("provision_users_modify.ldif"), {
857 "DOMAINDN": names.domaindn})
858 message("Adding computers container (permitted to fail)")
859 setup_add_ldif(samdb, setup_path("provision_computers_add.ldif"), {
860 "DOMAINDN": names.domaindn})
861 message("Modifying computers container")
862 setup_modify_ldif(samdb, setup_path("provision_computers_modify.ldif"), {
863 "DOMAINDN": names.domaindn})
864 message("Setting up sam.ldb data")
865 setup_add_ldif(samdb, setup_path("provision.ldif"), {
866 "DOMAINDN": names.domaindn,
867 "NETBIOSNAME": names.netbiosname,
868 "DEFAULTSITE": names.sitename,
869 "CONFIGDN": names.configdn,
870 "SERVERDN": names.serverdn
873 if fill == FILL_FULL:
874 message("Setting up sam.ldb users and groups")
875 setup_add_ldif(samdb, setup_path("provision_users.ldif"), {
876 "DOMAINDN": names.domaindn,
877 "DOMAINSID": str(domainsid),
878 "CONFIGDN": names.configdn,
879 "ADMINPASS_B64": b64encode(adminpass),
880 "KRBTGTPASS_B64": b64encode(krbtgtpass),
883 if serverrole == "domain controller":
884 message("Setting up self join")
885 setup_self_join(samdb, names=names, invocationid=invocationid,
887 machinepass=machinepass,
888 domainsid=domainsid, policyguid=policyguid,
889 setup_path=setup_path)
891 #We want to setup the index last, as adds are faster unindexed
892 message("Setting up sam.ldb index")
893 samdb.load_ldif_file_add(setup_path("provision_index.ldif"))
895 samdb.transaction_cancel()
898 samdb.transaction_commit()
903 FILL_NT4SYNC = "NT4SYNC"
906 def provision(setup_dir, message, session_info,
907 credentials, smbconf=None, targetdir=None, samdb_fill=FILL_FULL, realm=None,
908 rootdn=None, domaindn=None, schemadn=None, configdn=None,
910 domain=None, hostname=None, hostip=None, hostip6=None,
911 domainsid=None, adminpass=None, krbtgtpass=None, domainguid=None,
912 policyguid=None, invocationid=None, machinepass=None,
913 dnspass=None, root=None, nobody=None, nogroup=None, users=None,
914 wheel=None, backup=None, aci=None, serverrole=None,
915 ldap_backend=None, ldap_backend_type=None, sitename=None):
918 :note: caution, this wipes all existing data!
921 def setup_path(file):
922 return os.path.join(setup_dir, file)
924 if domainsid is None:
925 domainsid = security.random_sid()
927 domainsid = security.Sid(domainsid)
929 if policyguid is None:
930 policyguid = str(uuid.uuid4())
931 if adminpass is None:
932 adminpass = misc.random_password(12)
933 if krbtgtpass is None:
934 krbtgtpass = misc.random_password(12)
935 if machinepass is None:
936 machinepass = misc.random_password(12)
938 dnspass = misc.random_password(12)
939 root_uid = findnss_uid([root or "root"])
940 nobody_uid = findnss_uid([nobody or "nobody"])
941 users_gid = findnss_gid([users or "users"])
943 wheel_gid = findnss_gid(["wheel", "adm"])
945 wheel_gid = findnss_gid([wheel])
947 aci = "# no aci for local ldb"
949 if targetdir is not None:
950 if (not os.path.exists(os.path.join(targetdir, "etc"))):
951 os.makedirs(os.path.join(targetdir, "etc"))
952 smbconf = os.path.join(targetdir, "etc", "smb.conf")
954 # only install a new smb.conf if there isn't one there already
955 if not os.path.exists(smbconf):
956 make_smbconf(smbconf, setup_path, hostname, domain, realm, serverrole,
959 lp = param.LoadParm()
962 names = guess_names(lp=lp, hostname=hostname, domain=domain,
963 dnsdomain=realm, serverrole=serverrole, sitename=sitename,
964 rootdn=rootdn, domaindn=domaindn, configdn=configdn, schemadn=schemadn,
967 paths = provision_paths_from_lp(lp, names.dnsdomain)
970 hostip = socket.getaddrinfo(names.hostname, None, socket.AF_INET, socket.AI_CANONNAME, socket.IPPROTO_IP)[0][-1][0]
974 hostip6 = socket.getaddrinfo(names.hostname, None, socket.AF_INET6, socket.AI_CANONNAME, socket.IPPROTO_IP)[0][-1][0]
975 except socket.gaierror:
978 if serverrole is None:
979 serverrole = lp.get("server role")
981 assert serverrole in ("domain controller", "member server", "standalone")
982 if invocationid is None and serverrole == "domain controller":
983 invocationid = str(uuid.uuid4())
985 if not os.path.exists(paths.private_dir):
986 os.mkdir(paths.private_dir)
988 ldapi_url = "ldapi://%s" % urllib.quote(paths.s4_ldapi_path, safe="")
990 if ldap_backend is not None:
991 if ldap_backend == "ldapi":
992 # provision-backend will set this path suggested slapd command line / fedorads.inf
993 ldap_backend = "ldapi://%s" % urllib.quote(os.path.join(paths.private_dir, "ldap", "ldapi"), safe="")
995 # only install a new shares config db if there is none
996 if not os.path.exists(paths.shareconf):
997 message("Setting up share.ldb")
998 share_ldb = Ldb(paths.shareconf, session_info=session_info,
999 credentials=credentials, lp=lp)
1000 share_ldb.load_ldif_file_add(setup_path("share.ldif"))
1003 message("Setting up secrets.ldb")
1004 secrets_ldb = setup_secretsdb(paths.secrets, setup_path,
1005 session_info=session_info,
1006 credentials=credentials, lp=lp)
1008 message("Setting up the registry")
1009 setup_registry(paths.hklm, setup_path, session_info,
1010 credentials=credentials, lp=lp)
1012 message("Setting up templates db")
1013 setup_templatesdb(paths.templates, setup_path, session_info=session_info,
1014 credentials=credentials, lp=lp)
1016 message("Setting up idmap db")
1017 idmap = setup_idmapdb(paths.idmapdb, setup_path, session_info=session_info,
1018 credentials=credentials, lp=lp)
1020 samdb = setup_samdb(paths.samdb, setup_path, session_info=session_info,
1021 credentials=credentials, lp=lp, names=names,
1023 domainsid=domainsid,
1024 aci=aci, domainguid=domainguid, policyguid=policyguid,
1026 adminpass=adminpass, krbtgtpass=krbtgtpass,
1027 invocationid=invocationid,
1028 machinepass=machinepass, dnspass=dnspass,
1029 serverrole=serverrole, ldap_backend=ldap_backend,
1030 ldap_backend_type=ldap_backend_type)
1032 if lp.get("server role") == "domain controller":
1033 if paths.netlogon is None:
1034 message("Existing smb.conf does not have a [netlogon] share, but you are configuring a DC.")
1035 message("Please either remove %s or see the template at %s" %
1036 ( paths.smbconf, setup_path("provision.smb.conf.dc")))
1037 assert(paths.netlogon is not None)
1039 if paths.sysvol is None:
1040 message("Existing smb.conf does not have a [sysvol] share, but you are configuring a DC.")
1041 message("Please either remove %s or see the template at %s" %
1042 (paths.smbconf, setup_path("provision.smb.conf.dc")))
1043 assert(paths.sysvol is not None)
1045 policy_path = os.path.join(paths.sysvol, names.dnsdomain, "Policies",
1046 "{" + policyguid + "}")
1047 os.makedirs(policy_path, 0755)
1048 os.makedirs(os.path.join(policy_path, "Machine"), 0755)
1049 os.makedirs(os.path.join(policy_path, "User"), 0755)
1050 if not os.path.isdir(paths.netlogon):
1051 os.makedirs(paths.netlogon, 0755)
1053 if samdb_fill == FILL_FULL:
1054 setup_name_mappings(samdb, idmap, str(domainsid), names.domaindn,
1055 root_uid=root_uid, nobody_uid=nobody_uid,
1056 users_gid=users_gid, wheel_gid=wheel_gid)
1058 message("Setting up sam.ldb rootDSE marking as synchronized")
1059 setup_modify_ldif(samdb, setup_path("provision_rootdse_modify.ldif"))
1061 # Only make a zone file on the first DC, it should be replicated with DNS replication
1062 if serverrole == "domain controller":
1063 secrets_ldb = Ldb(paths.secrets, session_info=session_info,
1064 credentials=credentials, lp=lp)
1065 secretsdb_become_dc(secrets_ldb, setup_path, domain=domain, realm=names.realm,
1066 netbiosname=names.netbiosname, domainsid=domainsid,
1067 keytab_path=paths.keytab, samdb_url=paths.samdb,
1068 dns_keytab_path=paths.dns_keytab, dnspass=dnspass,
1069 machinepass=machinepass, dnsdomain=names.dnsdomain)
1071 samdb = SamDB(paths.samdb, session_info=session_info,
1072 credentials=credentials, lp=lp)
1074 domainguid = samdb.searchone(basedn=domaindn, attribute="objectGUID")
1075 assert isinstance(domainguid, str)
1076 hostguid = samdb.searchone(basedn=domaindn, attribute="objectGUID",
1077 expression="(&(objectClass=computer)(cn=%s))" % names.hostname,
1078 scope=SCOPE_SUBTREE)
1079 assert isinstance(hostguid, str)
1081 create_zone_file(paths.dns, setup_path, dnsdomain=names.dnsdomain,
1082 domaindn=names.domaindn, hostip=hostip,
1083 hostip6=hostip6, hostname=names.hostname,
1084 dnspass=dnspass, realm=names.realm,
1085 domainguid=domainguid, hostguid=hostguid)
1086 message("Please install the zone located in %s into your DNS server" % paths.dns)
1088 create_named_conf(paths.namedconf, setup_path, realm=names.realm,
1089 dnsdomain=names.dnsdomain, private_dir=paths.private_dir,
1090 keytab_name=paths.dns_keytab)
1091 message("See %s for example configuration statements for secure GSS-TSIG updates" % paths.namedconf)
1093 create_krb5_conf(paths.krb5conf, setup_path, dnsdomain=names.dnsdomain,
1094 hostname=names.hostname, realm=names.realm)
1095 message("A Kerberos configuration suitable for Samba 4 has been generated at %s" % paths.krb5conf)
1097 create_phpldapadmin_config(paths.phpldapadminconfig, setup_path,
1100 message("Please install the phpLDAPadmin configuration located at %s into /etc/phpldapadmin/config.php" % paths.phpldapadminconfig)
1102 message("Once the above files are installed, your Samba4 server will be ready to use")
1103 message("Server Role: %s" % serverrole)
1104 message("Hostname: %s" % names.hostname)
1105 message("NetBIOS Domain: %s" % names.domain)
1106 message("DNS Domain: %s" % names.dnsdomain)
1107 message("DOMAIN SID: %s" % str(domainsid))
1108 message("Admin password: %s" % adminpass)
1110 result = ProvisionResult()
1111 result.domaindn = domaindn
1112 result.paths = paths
1114 result.samdb = samdb
1118 def provision_become_dc(setup_dir=None,
1119 smbconf=None, targetdir=None, realm=None,
1120 rootdn=None, domaindn=None, schemadn=None, configdn=None,
1122 domain=None, hostname=None, domainsid=None,
1123 adminpass=None, krbtgtpass=None, domainguid=None,
1124 policyguid=None, invocationid=None, machinepass=None,
1125 dnspass=None, root=None, nobody=None, nogroup=None, users=None,
1126 wheel=None, backup=None, aci=None, serverrole=None,
1127 ldap_backend=None, ldap_backend_type=None, sitename=None):
1130 """print a message if quiet is not set."""
1133 return provision(setup_dir, message, system_session(), None,
1134 smbconf=smbconf, targetdir=targetdir, samdb_fill=FILL_DRS, realm=realm,
1135 rootdn=rootdn, domaindn=domaindn, schemadn=schemadn, configdn=configdn, serverdn=serverdn,
1136 domain=domain, hostname=hostname, hostip="127.0.0.1", domainsid=domainsid, machinepass=machinepass, serverrole="domain controller", sitename=sitename)
1139 def setup_db_config(setup_path, dbdir):
1140 """Setup a Berkeley database.
1142 :param setup_path: Setup path function.
1143 :param dbdir: Database directory."""
1144 if not os.path.isdir(os.path.join(dbdir, "bdb-logs")):
1145 os.makedirs(os.path.join(dbdir, "bdb-logs"), 0700)
1146 if not os.path.isdir(os.path.join(dbdir, "tmp")):
1147 os.makedirs(os.path.join(dbdir, "tmp"), 0700)
1149 setup_file(setup_path("DB_CONFIG"), os.path.join(dbdir, "DB_CONFIG"),
1150 {"LDAPDBDIR": dbdir})
1154 def provision_backend(setup_dir=None, message=None,
1155 smbconf=None, targetdir=None, realm=None,
1156 rootdn=None, domaindn=None, schemadn=None, configdn=None,
1157 domain=None, hostname=None, adminpass=None, root=None, serverrole=None,
1158 ldap_backend_type=None, ldap_backend_port=None):
1160 def setup_path(file):
1161 return os.path.join(setup_dir, file)
1163 if hostname is None:
1164 hostname = socket.gethostname().split(".")[0].lower()
1167 root = findnss(pwd.getpwnam, ["root"])[0]
1169 if adminpass is None:
1170 adminpass = misc.random_password(12)
1172 if targetdir is not None:
1173 if (not os.path.exists(os.path.join(targetdir, "etc"))):
1174 os.makedirs(os.path.join(targetdir, "etc"))
1175 smbconf = os.path.join(targetdir, "etc", "smb.conf")
1177 # only install a new smb.conf if there isn't one there already
1178 if not os.path.exists(smbconf):
1179 make_smbconf(smbconf, setup_path, hostname, domain, realm, serverrole,
1182 lp = param.LoadParm()
1185 names = guess_names(lp=lp, hostname=hostname, domain=domain,
1186 dnsdomain=realm, serverrole=serverrole,
1187 rootdn=rootdn, domaindn=domaindn, configdn=configdn,
1190 paths = provision_paths_from_lp(lp, names.dnsdomain)
1192 if not os.path.isdir(paths.ldapdir):
1193 os.makedirs(paths.ldapdir)
1194 schemadb_path = os.path.join(paths.ldapdir, "schema-tmp.ldb")
1196 os.unlink(schemadb_path)
1200 schemadb = Ldb(schemadb_path, lp=lp)
1202 prefixmap = open(setup_path("prefixMap.txt"), 'r').read()
1204 setup_add_ldif(schemadb, setup_path("provision_schema_basedn.ldif"),
1205 {"SCHEMADN": names.schemadn,
1207 "EXTENSIBLEOBJECT": "# no objectClass: extensibleObject for local ldb"
1209 setup_modify_ldif(schemadb,
1210 setup_path("provision_schema_basedn_modify.ldif"), \
1211 {"SCHEMADN": names.schemadn,
1212 "NETBIOSNAME": names.netbiosname,
1213 "DEFAULTSITE": DEFAULTSITE,
1214 "CONFIGDN": names.configdn,
1215 "SERVERDN": names.serverdn,
1216 "PREFIXMAP_B64": b64encode(prefixmap)
1219 setup_add_ldif(schemadb, setup_path("schema_samba4.ldif"),
1220 {"SCHEMADN": names.schemadn })
1221 setup_add_ldif(schemadb, setup_path("schema.ldif"),
1222 {"SCHEMADN": names.schemadn})
1224 if ldap_backend_type == "fedora-ds":
1225 if ldap_backend_port is not None:
1226 serverport = "ServerPort=%d" % ldap_backend_port
1230 setup_file(setup_path("fedorads.inf"), paths.fedoradsinf,
1232 "HOSTNAME": hostname,
1233 "DNSDOMAIN": names.dnsdomain,
1234 "LDAPDIR": paths.ldapdir,
1235 "DOMAINDN": names.domaindn,
1236 "LDAPMANAGERDN": names.ldapmanagerdn,
1237 "LDAPMANAGERPASS": adminpass,
1238 "SERVERPORT": serverport})
1240 setup_file(setup_path("fedorads-partitions.ldif"), paths.fedoradspartitions,
1241 {"CONFIGDN": names.configdn,
1242 "SCHEMADN": names.schemadn,
1245 mapping = "schema-map-fedora-ds-1.0"
1246 backend_schema = "99_ad.ldif"
1248 slapdcommand="Initailise Fedora DS with: setup-ds.pl --file=%s" % paths.fedoradsinf
1250 elif ldap_backend_type == "openldap":
1251 attrs = ["linkID", "lDAPDisplayName"]
1252 res = schemadb.search(expression="(&(&(linkID=*)(!(linkID:1.2.840.113556.1.4.803:=1)))(objectclass=attributeSchema))", base=names.schemadn, scope=SCOPE_SUBTREE, attrs=attrs)
1254 memberof_config = "# Generated from schema in %s\n" % schemadb_path
1255 refint_attributes = ""
1256 for i in range (0, len(res)):
1257 expression = "(&(objectclass=attributeSchema)(linkID=%d))" % (int(res[i]["linkID"][0])+1)
1258 target = schemadb.searchone(basedn=names.schemadn,
1259 expression=expression,
1260 attribute="lDAPDisplayName",
1261 scope=SCOPE_SUBTREE)
1262 if target is not None:
1263 refint_attributes = refint_attributes + " " + target + " " + res[i]["lDAPDisplayName"][0]
1265 memberof_config += read_and_sub_file(setup_path("memberof.conf"),
1266 { "MEMBER_ATTR" : str(res[i]["lDAPDisplayName"][0]),
1267 "MEMBEROF_ATTR" : str(target) })
1269 refint_config = read_and_sub_file(setup_path("refint.conf"),
1270 { "LINK_ATTRS" : refint_attributes})
1272 setup_file(setup_path("slapd.conf"), paths.slapdconf,
1273 {"DNSDOMAIN": names.dnsdomain,
1274 "LDAPDIR": paths.ldapdir,
1275 "DOMAINDN": names.domaindn,
1276 "CONFIGDN": names.configdn,
1277 "SCHEMADN": names.schemadn,
1278 "MEMBEROF_CONFIG": memberof_config,
1279 "REFINT_CONFIG": refint_config})
1280 setup_file(setup_path("modules.conf"), paths.modulesconf,
1281 {"REALM": names.realm})
1283 setup_db_config(setup_path, os.path.join(paths.ldapdir, "db", "user"))
1284 setup_db_config(setup_path, os.path.join(paths.ldapdir, "db", "config"))
1285 setup_db_config(setup_path, os.path.join(paths.ldapdir, "db", "schema"))
1287 if not os.path.exists(os.path.join(paths.ldapdir, "db", "samba", "cn=samba")):
1288 os.makedirs(os.path.join(paths.ldapdir, "db", "samba", "cn=samba"))
1290 setup_file(setup_path("cn=samba.ldif"),
1291 os.path.join(paths.ldapdir, "db", "samba", "cn=samba.ldif"),
1292 { "UUID": str(uuid.uuid4()),
1293 "LDAPTIME": timestring(int(time.time()))} )
1294 setup_file(setup_path("cn=samba-admin.ldif"),
1295 os.path.join(paths.ldapdir, "db", "samba", "cn=samba", "cn=samba-admin.ldif"),
1296 {"LDAPADMINPASS_B64": b64encode(adminpass),
1297 "UUID": str(uuid.uuid4()),
1298 "LDAPTIME": timestring(int(time.time()))} )
1300 mapping = "schema-map-openldap-2.3"
1301 backend_schema = "backend-schema.schema"
1303 ldapi_uri = "ldapi://" + urllib.quote(os.path.join(paths.private_dir, "ldap", "ldapi"), safe="")
1304 if ldap_backend_port is not None:
1305 server_port_string = " -h ldap://0.0.0.0:%d" % ldap_backend_port
1307 server_port_string = ""
1308 slapdcommand="Start slapd with: slapd -f " + paths.ldapdir + "/slapd.conf -h " + ldapi_uri + server_port_string
1311 schema_command = "bin/ad2oLschema --option=convert:target=" + ldap_backend_type + " -I " + setup_path(mapping) + " -H tdb://" + schemadb_path + " -O " + os.path.join(paths.ldapdir, backend_schema)
1313 os.system(schema_command)
1315 message("Your %s Backend for Samba4 is now configured, and is ready to be started" % ldap_backend_type)
1316 message("Server Role: %s" % serverrole)
1317 message("Hostname: %s" % names.hostname)
1318 message("DNS Domain: %s" % names.dnsdomain)
1319 message("Base DN: %s" % names.domaindn)
1321 if ldap_backend_type == "openldap":
1322 message("LDAP admin user: samba-admin")
1324 message("LDAP admin DN: %s" % names.ldapmanagerdn)
1326 message("LDAP admin password: %s" % adminpass)
1327 message(slapdcommand)
1330 def create_phpldapadmin_config(path, setup_path, ldapi_uri):
1331 """Create a PHP LDAP admin configuration file.
1333 :param path: Path to write the configuration to.
1334 :param setup_path: Function to generate setup paths.
1336 setup_file(setup_path("phpldapadmin-config.php"), path,
1337 {"S4_LDAPI_URI": ldapi_uri})
1340 def create_zone_file(path, setup_path, dnsdomain, domaindn,
1341 hostip, hostip6, hostname, dnspass, realm, domainguid, hostguid):
1342 """Write out a DNS zone file, from the info in the current database.
1344 :param path: Path of the new zone file.
1345 :param setup_path: Setup path function.
1346 :param dnsdomain: DNS Domain name
1347 :param domaindn: DN of the Domain
1348 :param hostip: Local IPv4 IP
1349 :param hostip6: Local IPv6 IP
1350 :param hostname: Local hostname
1351 :param dnspass: Password for DNS
1352 :param realm: Realm name
1353 :param domainguid: GUID of the domain.
1354 :param hostguid: GUID of the host.
1356 assert isinstance(domainguid, str)
1358 if hostip6 is not None:
1359 hostip6_base_line = " IN AAAA " + hostip6
1360 hostip6_host_line = hostname + " IN AAAA " + hostip6
1362 hostip6_base_line = ""
1363 hostip6_host_line = ""
1365 setup_file(setup_path("provision.zone"), path, {
1366 "DNSPASS_B64": b64encode(dnspass),
1367 "HOSTNAME": hostname,
1368 "DNSDOMAIN": dnsdomain,
1371 "DOMAINGUID": domainguid,
1372 "DATESTRING": time.strftime("%Y%m%d%H"),
1373 "DEFAULTSITE": DEFAULTSITE,
1374 "HOSTGUID": hostguid,
1375 "HOSTIP6_BASE_LINE": hostip6_base_line,
1376 "HOSTIP6_HOST_LINE": hostip6_host_line,
1380 def create_named_conf(path, setup_path, realm, dnsdomain,
1381 private_dir, keytab_name):
1382 """Write out a file containing zone statements suitable for inclusion in a
1383 named.conf file (including GSS-TSIG configuration).
1385 :param path: Path of the new named.conf file.
1386 :param setup_path: Setup path function.
1387 :param realm: Realm name
1388 :param dnsdomain: DNS Domain name
1389 :param private_dir: Path to private directory
1390 :param keytab_name: File name of DNS keytab file
1393 setup_file(setup_path("named.conf"), path, {
1394 "DNSDOMAIN": dnsdomain,
1396 "REALM_WC": "*." + ".".join(realm.split(".")[1:]),
1397 "DNS_KEYTAB": keytab_name,
1398 "DNS_KEYTAB_ABS": os.path.join(private_dir, keytab_name),
1401 def create_krb5_conf(path, setup_path, dnsdomain, hostname, realm):
1402 """Write out a file containing zone statements suitable for inclusion in a
1403 named.conf file (including GSS-TSIG configuration).
1405 :param path: Path of the new named.conf file.
1406 :param setup_path: Setup path function.
1407 :param dnsdomain: DNS Domain name
1408 :param hostname: Local hostname
1409 :param realm: Realm name
1412 setup_file(setup_path("krb5.conf"), path, {
1413 "DNSDOMAIN": dnsdomain,
1414 "HOSTNAME": hostname,
1419 def load_schema(setup_path, samdb, schemadn, netbiosname, configdn, sitename):
1420 """Load schema for the SamDB.
1422 :param samdb: Load a schema into a SamDB.
1423 :param setup_path: Setup path function.
1424 :param schemadn: DN of the schema
1425 :param netbiosname: NetBIOS name of the host.
1426 :param configdn: DN of the configuration
1428 schema_data = open(setup_path("schema.ldif"), 'r').read()
1429 schema_data += open(setup_path("schema_samba4.ldif"), 'r').read()
1430 schema_data = substitute_var(schema_data, {"SCHEMADN": schemadn})
1431 prefixmap = open(setup_path("prefixMap.txt"), 'r').read()
1432 prefixmap = b64encode(prefixmap)
1434 head_data = open(setup_path("provision_schema_basedn_modify.ldif"), 'r').read()
1435 head_data = substitute_var(head_data, {
1436 "SCHEMADN": schemadn,
1437 "NETBIOSNAME": netbiosname,
1438 "CONFIGDN": configdn,
1439 "DEFAULTSITE":sitename,
1440 "PREFIXMAP_B64":prefixmap
1442 samdb.attach_schema_from_ldif(head_data, schema_data)