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.namedtxt = os.path.join(paths.private_dir, "named.txt")
248 paths.krb5conf = os.path.join(paths.private_dir, "krb5.conf")
249 paths.winsdb = os.path.join(paths.private_dir, "wins.ldb")
250 paths.s4_ldapi_path = os.path.join(paths.private_dir, "ldapi")
251 paths.phpldapadminconfig = os.path.join(paths.private_dir,
252 "phpldapadmin-config.php")
253 paths.ldapdir = os.path.join(paths.private_dir,
255 paths.slapdconf = os.path.join(paths.ldapdir,
257 paths.modulesconf = os.path.join(paths.ldapdir,
259 paths.memberofconf = os.path.join(paths.ldapdir,
261 paths.fedoradsinf = os.path.join(paths.ldapdir,
263 paths.fedoradspartitions = os.path.join(paths.ldapdir,
264 "fedorads-partitions.ldif")
265 paths.hklm = "hklm.ldb"
266 paths.hkcr = "hkcr.ldb"
267 paths.hkcu = "hkcu.ldb"
268 paths.hku = "hku.ldb"
269 paths.hkpd = "hkpd.ldb"
270 paths.hkpt = "hkpt.ldb"
272 paths.sysvol = lp.get("path", "sysvol")
274 paths.netlogon = lp.get("path", "netlogon")
276 paths.smbconf = lp.configfile()
281 def guess_names(lp=None, hostname=None, domain=None, dnsdomain=None, serverrole=None,
282 rootdn=None, domaindn=None, configdn=None, schemadn=None, serverdn=None,
284 """Guess configuration settings to use."""
287 hostname = socket.gethostname().split(".")[0].lower()
289 netbiosname = hostname.upper()
290 if not valid_netbios_name(netbiosname):
291 raise InvalidNetbiosName(netbiosname)
293 hostname = hostname.lower()
295 if dnsdomain is None:
296 dnsdomain = lp.get("realm")
298 if serverrole is None:
299 serverrole = lp.get("server role")
301 assert dnsdomain is not None
302 realm = dnsdomain.upper()
304 if lp.get("realm").upper() != realm:
305 raise Exception("realm '%s' in %s must match chosen realm '%s'" %
306 (lp.get("realm"), lp.configfile(), realm))
308 dnsdomain = dnsdomain.lower()
310 if serverrole == "domain controller":
312 domain = lp.get("workgroup")
314 domaindn = "DC=" + dnsdomain.replace(".", ",DC=")
315 if lp.get("workgroup").upper() != domain.upper():
316 raise Exception("workgroup '%s' in smb.conf must match chosen domain '%s'",
317 lp.get("workgroup"), domain)
321 domaindn = "CN=" + netbiosname
323 assert domain is not None
324 domain = domain.upper()
325 if not valid_netbios_name(domain):
326 raise InvalidNetbiosName(domain)
332 configdn = "CN=Configuration," + rootdn
334 schemadn = "CN=Schema," + configdn
339 names = ProvisionNames()
340 names.rootdn = rootdn
341 names.domaindn = domaindn
342 names.configdn = configdn
343 names.schemadn = schemadn
344 names.ldapmanagerdn = "CN=Manager," + rootdn
345 names.dnsdomain = dnsdomain
346 names.domain = domain
348 names.netbiosname = netbiosname
349 names.hostname = hostname
350 names.sitename = sitename
351 names.serverdn = "CN=%s,CN=Servers,CN=%s,CN=Sites,%s" % (netbiosname, sitename, configdn)
356 def make_smbconf(smbconf, setup_path, hostname, domain, realm, serverrole,
359 hostname = socket.gethostname().split(".")[0].lower()
361 if serverrole is None:
362 serverrole = "standalone"
364 assert serverrole in ("domain controller", "member server", "standalone")
365 if serverrole == "domain controller":
367 elif serverrole == "member server":
368 smbconfsuffix = "member"
369 elif serverrole == "standalone":
370 smbconfsuffix = "standalone"
372 assert domain is not None
373 assert realm is not None
375 default_lp = param.LoadParm()
376 #Load non-existant file
377 default_lp.load(smbconf)
379 if targetdir is not None:
380 privatedir_line = "private dir = " + os.path.abspath(os.path.join(targetdir, "private"))
381 lockdir_line = "lock dir = " + os.path.abspath(targetdir)
383 default_lp.set("lock dir", os.path.abspath(targetdir))
388 sysvol = os.path.join(default_lp.get("lock dir"), "sysvol")
389 netlogon = os.path.join(sysvol, realm.lower(), "scripts")
391 setup_file(setup_path("provision.smb.conf.%s" % smbconfsuffix),
393 "HOSTNAME": hostname,
396 "SERVERROLE": serverrole,
397 "NETLOGONPATH": netlogon,
398 "SYSVOLPATH": sysvol,
399 "PRIVATEDIR_LINE": privatedir_line,
400 "LOCKDIR_LINE": lockdir_line
405 def setup_name_mappings(samdb, idmap, sid, domaindn, root_uid, nobody_uid,
406 users_gid, wheel_gid):
407 """setup reasonable name mappings for sam names to unix names.
409 :param samdb: SamDB object.
410 :param idmap: IDmap db object.
411 :param sid: The domain sid.
412 :param domaindn: The domain DN.
413 :param root_uid: uid of the UNIX root user.
414 :param nobody_uid: uid of the UNIX nobody user.
415 :param users_gid: gid of the UNIX users group.
416 :param wheel_gid: gid of the UNIX wheel group."""
417 # add some foreign sids if they are not present already
418 samdb.add_foreign(domaindn, "S-1-5-7", "Anonymous")
419 samdb.add_foreign(domaindn, "S-1-1-0", "World")
420 samdb.add_foreign(domaindn, "S-1-5-2", "Network")
421 samdb.add_foreign(domaindn, "S-1-5-18", "System")
422 samdb.add_foreign(domaindn, "S-1-5-11", "Authenticated Users")
424 idmap.setup_name_mapping("S-1-5-7", idmap.TYPE_UID, nobody_uid)
425 idmap.setup_name_mapping("S-1-5-32-544", idmap.TYPE_GID, wheel_gid)
427 idmap.setup_name_mapping(sid + "-500", idmap.TYPE_UID, root_uid)
428 idmap.setup_name_mapping(sid + "-513", idmap.TYPE_GID, users_gid)
431 def setup_samdb_partitions(samdb_path, setup_path, message, lp, session_info,
433 serverrole, ldap_backend=None,
434 ldap_backend_type=None, erase=False):
435 """Setup the partitions for the SAM database.
437 Alternatively, provision() may call this, and then populate the database.
439 :note: This will wipe the Sam Database!
441 :note: This function always removes the local SAM LDB file. The erase
442 parameter controls whether to erase the existing data, which
443 may not be stored locally but in LDAP.
445 assert session_info is not None
447 samdb = SamDB(samdb_path, session_info=session_info,
448 credentials=credentials, lp=lp)
454 os.unlink(samdb_path)
456 samdb = SamDB(samdb_path, session_info=session_info,
457 credentials=credentials, lp=lp)
459 #Add modules to the list to activate them by default
460 #beware often order is important
462 # Some Known ordering constraints:
463 # - rootdse must be first, as it makes redirects from "" -> cn=rootdse
464 # - objectclass must be before password_hash, because password_hash checks
465 # that the objectclass is of type person (filled in by objectclass
466 # module when expanding the objectclass list)
467 # - partition must be last
468 # - each partition has its own module list then
469 modules_list = ["rootdse",
485 modules_list2 = ["show_deleted",
488 domaindn_ldb = "users.ldb"
489 if ldap_backend is not None:
490 domaindn_ldb = ldap_backend
491 configdn_ldb = "configuration.ldb"
492 if ldap_backend is not None:
493 configdn_ldb = ldap_backend
494 schemadn_ldb = "schema.ldb"
495 if ldap_backend is not None:
496 schema_ldb = ldap_backend
497 schemadn_ldb = ldap_backend
499 if ldap_backend_type == "fedora-ds":
500 backend_modules = ["nsuniqueid", "paged_searches"]
501 # We can handle linked attributes here, as we don't have directory-side subtree operations
502 tdb_modules_list = ["linked_attributes"]
503 elif ldap_backend_type == "openldap":
504 backend_modules = ["normalise", "entryuuid", "paged_searches"]
505 # OpenLDAP handles subtree renames, so we don't want to do any of these things
506 tdb_modules_list = None
507 elif serverrole == "domain controller":
508 backend_modules = ["repl_meta_data"]
510 backend_modules = ["objectguid"]
512 if tdb_modules_list is None:
513 tdb_modules_list_as_string = ""
515 tdb_modules_list_as_string = ","+",".join(tdb_modules_list)
517 samdb.transaction_start()
519 setup_add_ldif(samdb, setup_path("provision_partitions.ldif"), {
520 "SCHEMADN": names.schemadn,
521 "SCHEMADN_LDB": schemadn_ldb,
522 "SCHEMADN_MOD2": ",objectguid",
523 "CONFIGDN": names.configdn,
524 "CONFIGDN_LDB": configdn_ldb,
525 "DOMAINDN": names.domaindn,
526 "DOMAINDN_LDB": domaindn_ldb,
527 "SCHEMADN_MOD": "schema_fsmo,instancetype",
528 "CONFIGDN_MOD": "naming_fsmo,instancetype",
529 "DOMAINDN_MOD": "pdc_fsmo,password_hash,instancetype",
530 "MODULES_LIST": ",".join(modules_list),
531 "TDB_MODULES_LIST": tdb_modules_list_as_string,
532 "MODULES_LIST2": ",".join(modules_list2),
533 "BACKEND_MOD": ",".join(backend_modules),
537 samdb.transaction_cancel()
540 samdb.transaction_commit()
542 samdb = SamDB(samdb_path, session_info=session_info,
543 credentials=credentials, lp=lp)
545 samdb.transaction_start()
547 message("Setting up sam.ldb attributes")
548 samdb.load_ldif_file_add(setup_path("provision_init.ldif"))
550 message("Setting up sam.ldb rootDSE")
551 setup_samdb_rootdse(samdb, setup_path, names)
554 message("Erasing data from partitions")
555 samdb.erase_partitions()
558 samdb.transaction_cancel()
561 samdb.transaction_commit()
566 def secretsdb_become_dc(secretsdb, setup_path, domain, realm, dnsdomain,
567 netbiosname, domainsid, keytab_path, samdb_url,
568 dns_keytab_path, dnspass, machinepass):
569 """Add DC-specific bits to a secrets database.
571 :param secretsdb: Ldb Handle to the secrets database
572 :param setup_path: Setup path function
573 :param machinepass: Machine password
575 setup_ldb(secretsdb, setup_path("secrets_dc.ldif"), {
576 "MACHINEPASS_B64": b64encode(machinepass),
579 "DNSDOMAIN": dnsdomain,
580 "DOMAINSID": str(domainsid),
581 "SECRETS_KEYTAB": keytab_path,
582 "NETBIOSNAME": netbiosname,
583 "SAM_LDB": samdb_url,
584 "DNS_KEYTAB": dns_keytab_path,
585 "DNSPASS_B64": b64encode(dnspass),
589 def setup_secretsdb(path, setup_path, session_info, credentials, lp):
590 """Setup the secrets database.
592 :param path: Path to the secrets database.
593 :param setup_path: Get the path to a setup file.
594 :param session_info: Session info.
595 :param credentials: Credentials
596 :param lp: Loadparm context
597 :return: LDB handle for the created secrets database
599 if os.path.exists(path):
601 secrets_ldb = Ldb(path, session_info=session_info, credentials=credentials,
604 secrets_ldb.load_ldif_file_add(setup_path("secrets_init.ldif"))
605 secrets_ldb = Ldb(path, session_info=session_info, credentials=credentials,
607 secrets_ldb.load_ldif_file_add(setup_path("secrets.ldif"))
609 if credentials is not None and credentials.authentication_requested():
610 if credentials.get_bind_dn() is not None:
611 setup_add_ldif(secrets_ldb, setup_path("secrets_simple_ldap.ldif"), {
612 "LDAPMANAGERDN": credentials.get_bind_dn(),
613 "LDAPMANAGERPASS_B64": b64encode(credentials.get_password())
616 setup_add_ldif(secrets_ldb, setup_path("secrets_sasl_ldap.ldif"), {
617 "LDAPADMINUSER": credentials.get_username(),
618 "LDAPADMINREALM": credentials.get_realm(),
619 "LDAPADMINPASS_B64": b64encode(credentials.get_password())
625 def setup_templatesdb(path, setup_path, session_info, credentials, lp):
626 """Setup the templates database.
628 :param path: Path to the database.
629 :param setup_path: Function for obtaining the path to setup files.
630 :param session_info: Session info
631 :param credentials: Credentials
632 :param lp: Loadparm context
634 templates_ldb = SamDB(path, session_info=session_info,
635 credentials=credentials, lp=lp)
636 templates_ldb.erase()
637 templates_ldb.load_ldif_file_add(setup_path("provision_templates.ldif"))
640 def setup_registry(path, setup_path, session_info, credentials, lp):
641 """Setup the registry.
643 :param path: Path to the registry database
644 :param setup_path: Function that returns the path to a setup.
645 :param session_info: Session information
646 :param credentials: Credentials
647 :param lp: Loadparm context
649 reg = registry.Registry()
650 hive = registry.open_ldb(path, session_info=session_info,
651 credentials=credentials, lp_ctx=lp)
652 reg.mount_hive(hive, "HKEY_LOCAL_MACHINE")
653 provision_reg = setup_path("provision.reg")
654 assert os.path.exists(provision_reg)
655 reg.diff_apply(provision_reg)
658 def setup_idmapdb(path, setup_path, session_info, credentials, lp):
659 """Setup the idmap database.
661 :param path: path to the idmap database
662 :param setup_path: Function that returns a path to a setup file
663 :param session_info: Session information
664 :param credentials: Credentials
665 :param lp: Loadparm context
667 if os.path.exists(path):
670 idmap_ldb = IDmapDB(path, session_info=session_info,
671 credentials=credentials, lp=lp)
674 idmap_ldb.load_ldif_file_add(setup_path("idmap_init.ldif"))
678 def setup_samdb_rootdse(samdb, setup_path, names):
679 """Setup the SamDB rootdse.
681 :param samdb: Sam Database handle
682 :param setup_path: Obtain setup path
684 setup_add_ldif(samdb, setup_path("provision_rootdse_add.ldif"), {
685 "SCHEMADN": names.schemadn,
686 "NETBIOSNAME": names.netbiosname,
687 "DNSDOMAIN": names.dnsdomain,
688 "REALM": names.realm,
689 "DNSNAME": "%s.%s" % (names.hostname, names.dnsdomain),
690 "DOMAINDN": names.domaindn,
691 "ROOTDN": names.rootdn,
692 "CONFIGDN": names.configdn,
693 "SERVERDN": names.serverdn,
697 def setup_self_join(samdb, names,
698 machinepass, dnspass,
699 domainsid, invocationid, setup_path,
701 """Join a host to its own domain."""
702 assert isinstance(invocationid, str)
703 setup_add_ldif(samdb, setup_path("provision_self_join.ldif"), {
704 "CONFIGDN": names.configdn,
705 "SCHEMADN": names.schemadn,
706 "DOMAINDN": names.domaindn,
707 "SERVERDN": names.serverdn,
708 "INVOCATIONID": invocationid,
709 "NETBIOSNAME": names.netbiosname,
710 "DEFAULTSITE": names.sitename,
711 "DNSNAME": "%s.%s" % (names.hostname, names.dnsdomain),
712 "MACHINEPASS_B64": b64encode(machinepass),
713 "DNSPASS_B64": b64encode(dnspass),
714 "REALM": names.realm,
715 "DOMAIN": names.domain,
716 "DNSDOMAIN": names.dnsdomain})
717 setup_add_ldif(samdb, setup_path("provision_group_policy.ldif"), {
718 "POLICYGUID": policyguid,
719 "DNSDOMAIN": names.dnsdomain,
720 "DOMAINSID": str(domainsid),
721 "DOMAINDN": names.domaindn})
724 def setup_samdb(path, setup_path, session_info, credentials, lp,
726 domainsid, aci, domainguid, policyguid,
727 fill, adminpass, krbtgtpass,
728 machinepass, invocationid, dnspass,
729 serverrole, ldap_backend=None,
730 ldap_backend_type=None):
731 """Setup a complete SAM Database.
733 :note: This will wipe the main SAM database file!
736 erase = (fill != FILL_DRS)
738 # Also wipes the database
739 setup_samdb_partitions(path, setup_path, message=message, lp=lp,
740 credentials=credentials, session_info=session_info,
742 ldap_backend=ldap_backend, serverrole=serverrole,
743 ldap_backend_type=ldap_backend_type, erase=erase)
745 samdb = SamDB(path, session_info=session_info,
746 credentials=credentials, lp=lp)
749 # We want to finish here, but setup the index before we do so
750 message("Setting up sam.ldb index")
751 samdb.load_ldif_file_add(setup_path("provision_index.ldif"))
754 message("Pre-loading the Samba 4 and AD schema")
755 samdb.set_domain_sid(domainsid)
756 if serverrole == "domain controller":
757 samdb.set_invocation_id(invocationid)
759 load_schema(setup_path, samdb, names.schemadn, names.netbiosname,
760 names.configdn, names.sitename)
762 samdb.transaction_start()
765 message("Adding DomainDN: %s (permitted to fail)" % names.domaindn)
766 if serverrole == "domain controller":
767 domain_oc = "domainDNS"
769 domain_oc = "samba4LocalDomain"
771 setup_add_ldif(samdb, setup_path("provision_basedn.ldif"), {
772 "DOMAINDN": names.domaindn,
774 "DOMAIN_OC": domain_oc
777 message("Modifying DomainDN: " + names.domaindn + "")
778 if domainguid is not None:
779 domainguid_mod = "replace: objectGUID\nobjectGUID: %s\n-" % domainguid
783 setup_modify_ldif(samdb, setup_path("provision_basedn_modify.ldif"), {
784 "LDAPTIME": timestring(int(time.time())),
785 "DOMAINSID": str(domainsid),
786 "SCHEMADN": names.schemadn,
787 "NETBIOSNAME": names.netbiosname,
788 "DEFAULTSITE": names.sitename,
789 "CONFIGDN": names.configdn,
790 "SERVERDN": names.serverdn,
791 "POLICYGUID": policyguid,
792 "DOMAINDN": names.domaindn,
793 "DOMAINGUID_MOD": domainguid_mod,
796 message("Adding configuration container (permitted to fail)")
797 setup_add_ldif(samdb, setup_path("provision_configuration_basedn.ldif"), {
798 "CONFIGDN": names.configdn,
800 "EXTENSIBLEOBJECT": "# no objectClass: extensibleObject for local ldb",
802 message("Modifying configuration container")
803 setup_modify_ldif(samdb, setup_path("provision_configuration_basedn_modify.ldif"), {
804 "CONFIGDN": names.configdn,
805 "SCHEMADN": names.schemadn,
808 message("Adding schema container (permitted to fail)")
809 setup_add_ldif(samdb, setup_path("provision_schema_basedn.ldif"), {
810 "SCHEMADN": names.schemadn,
812 "EXTENSIBLEOBJECT": "# no objectClass: extensibleObject for local ldb"
814 message("Modifying schema container")
816 prefixmap = open(setup_path("prefixMap.txt"), 'r').read()
818 setup_modify_ldif(samdb,
819 setup_path("provision_schema_basedn_modify.ldif"), {
820 "SCHEMADN": names.schemadn,
821 "NETBIOSNAME": names.netbiosname,
822 "DEFAULTSITE": names.sitename,
823 "CONFIGDN": names.configdn,
824 "SERVERDN": names.serverdn,
825 "PREFIXMAP_B64": b64encode(prefixmap)
828 message("Setting up sam.ldb Samba4 schema")
829 setup_add_ldif(samdb, setup_path("schema_samba4.ldif"),
830 {"SCHEMADN": names.schemadn })
831 message("Setting up sam.ldb AD schema")
832 setup_add_ldif(samdb, setup_path("schema.ldif"),
833 {"SCHEMADN": names.schemadn})
835 message("Setting up sam.ldb configuration data")
836 setup_add_ldif(samdb, setup_path("provision_configuration.ldif"), {
837 "CONFIGDN": names.configdn,
838 "NETBIOSNAME": names.netbiosname,
839 "DEFAULTSITE": names.sitename,
840 "DNSDOMAIN": names.dnsdomain,
841 "DOMAIN": names.domain,
842 "SCHEMADN": names.schemadn,
843 "DOMAINDN": names.domaindn,
844 "SERVERDN": names.serverdn
847 message("Setting up display specifiers")
848 setup_add_ldif(samdb, setup_path("display_specifiers.ldif"),
849 {"CONFIGDN": names.configdn})
851 message("Adding users container (permitted to fail)")
852 setup_add_ldif(samdb, setup_path("provision_users_add.ldif"), {
853 "DOMAINDN": names.domaindn})
854 message("Modifying users container")
855 setup_modify_ldif(samdb, setup_path("provision_users_modify.ldif"), {
856 "DOMAINDN": names.domaindn})
857 message("Adding computers container (permitted to fail)")
858 setup_add_ldif(samdb, setup_path("provision_computers_add.ldif"), {
859 "DOMAINDN": names.domaindn})
860 message("Modifying computers container")
861 setup_modify_ldif(samdb, setup_path("provision_computers_modify.ldif"), {
862 "DOMAINDN": names.domaindn})
863 message("Setting up sam.ldb data")
864 setup_add_ldif(samdb, setup_path("provision.ldif"), {
865 "DOMAINDN": names.domaindn,
866 "NETBIOSNAME": names.netbiosname,
867 "DEFAULTSITE": names.sitename,
868 "CONFIGDN": names.configdn,
869 "SERVERDN": names.serverdn
872 if fill == FILL_FULL:
873 message("Setting up sam.ldb users and groups")
874 setup_add_ldif(samdb, setup_path("provision_users.ldif"), {
875 "DOMAINDN": names.domaindn,
876 "DOMAINSID": str(domainsid),
877 "CONFIGDN": names.configdn,
878 "ADMINPASS_B64": b64encode(adminpass),
879 "KRBTGTPASS_B64": b64encode(krbtgtpass),
882 if serverrole == "domain controller":
883 message("Setting up self join")
884 setup_self_join(samdb, names=names, invocationid=invocationid,
886 machinepass=machinepass,
887 domainsid=domainsid, policyguid=policyguid,
888 setup_path=setup_path)
890 #We want to setup the index last, as adds are faster unindexed
891 message("Setting up sam.ldb index")
892 samdb.load_ldif_file_add(setup_path("provision_index.ldif"))
894 samdb.transaction_cancel()
897 samdb.transaction_commit()
902 FILL_NT4SYNC = "NT4SYNC"
905 def provision(setup_dir, message, session_info,
906 credentials, smbconf=None, targetdir=None, samdb_fill=FILL_FULL, realm=None,
907 rootdn=None, domaindn=None, schemadn=None, configdn=None,
909 domain=None, hostname=None, hostip=None, hostip6=None,
910 domainsid=None, adminpass=None, krbtgtpass=None, domainguid=None,
911 policyguid=None, invocationid=None, machinepass=None,
912 dnspass=None, root=None, nobody=None, nogroup=None, users=None,
913 wheel=None, backup=None, aci=None, serverrole=None,
914 ldap_backend=None, ldap_backend_type=None, sitename=None):
917 :note: caution, this wipes all existing data!
920 def setup_path(file):
921 return os.path.join(setup_dir, file)
923 if domainsid is None:
924 domainsid = security.random_sid()
926 domainsid = security.Sid(domainsid)
928 if policyguid is None:
929 policyguid = str(uuid.uuid4())
930 if adminpass is None:
931 adminpass = misc.random_password(12)
932 if krbtgtpass is None:
933 krbtgtpass = misc.random_password(12)
934 if machinepass is None:
935 machinepass = misc.random_password(12)
937 dnspass = misc.random_password(12)
938 root_uid = findnss_uid([root or "root"])
939 nobody_uid = findnss_uid([nobody or "nobody"])
940 users_gid = findnss_gid([users or "users"])
942 wheel_gid = findnss_gid(["wheel", "adm"])
944 wheel_gid = findnss_gid([wheel])
946 aci = "# no aci for local ldb"
948 if targetdir is not None:
949 if (not os.path.exists(os.path.join(targetdir, "etc"))):
950 os.makedirs(os.path.join(targetdir, "etc"))
951 smbconf = os.path.join(targetdir, "etc", "smb.conf")
953 # only install a new smb.conf if there isn't one there already
954 if not os.path.exists(smbconf):
955 make_smbconf(smbconf, setup_path, hostname, domain, realm, serverrole,
958 lp = param.LoadParm()
961 names = guess_names(lp=lp, hostname=hostname, domain=domain,
962 dnsdomain=realm, serverrole=serverrole, sitename=sitename,
963 rootdn=rootdn, domaindn=domaindn, configdn=configdn, schemadn=schemadn,
966 paths = provision_paths_from_lp(lp, names.dnsdomain)
969 hostip = socket.getaddrinfo(names.hostname, None, socket.AF_INET, socket.AI_CANONNAME, socket.IPPROTO_IP)[0][-1][0]
973 hostip6 = socket.getaddrinfo(names.hostname, None, socket.AF_INET6, socket.AI_CANONNAME, socket.IPPROTO_IP)[0][-1][0]
974 except socket.gaierror:
977 if serverrole is None:
978 serverrole = lp.get("server role")
980 assert serverrole in ("domain controller", "member server", "standalone")
981 if invocationid is None and serverrole == "domain controller":
982 invocationid = str(uuid.uuid4())
984 if not os.path.exists(paths.private_dir):
985 os.mkdir(paths.private_dir)
987 ldapi_url = "ldapi://%s" % urllib.quote(paths.s4_ldapi_path, safe="")
989 if ldap_backend is not None:
990 if ldap_backend == "ldapi":
991 # provision-backend will set this path suggested slapd command line / fedorads.inf
992 ldap_backend = "ldapi://%s" % urllib.quote(os.path.join(paths.private_dir, "ldap", "ldapi"), safe="")
994 # only install a new shares config db if there is none
995 if not os.path.exists(paths.shareconf):
996 message("Setting up share.ldb")
997 share_ldb = Ldb(paths.shareconf, session_info=session_info,
998 credentials=credentials, lp=lp)
999 share_ldb.load_ldif_file_add(setup_path("share.ldif"))
1002 message("Setting up secrets.ldb")
1003 secrets_ldb = setup_secretsdb(paths.secrets, setup_path,
1004 session_info=session_info,
1005 credentials=credentials, lp=lp)
1007 message("Setting up the registry")
1008 setup_registry(paths.hklm, setup_path, session_info,
1009 credentials=credentials, lp=lp)
1011 message("Setting up templates db")
1012 setup_templatesdb(paths.templates, setup_path, session_info=session_info,
1013 credentials=credentials, lp=lp)
1015 message("Setting up idmap db")
1016 idmap = setup_idmapdb(paths.idmapdb, setup_path, session_info=session_info,
1017 credentials=credentials, lp=lp)
1019 samdb = setup_samdb(paths.samdb, setup_path, session_info=session_info,
1020 credentials=credentials, lp=lp, names=names,
1022 domainsid=domainsid,
1023 aci=aci, domainguid=domainguid, policyguid=policyguid,
1025 adminpass=adminpass, krbtgtpass=krbtgtpass,
1026 invocationid=invocationid,
1027 machinepass=machinepass, dnspass=dnspass,
1028 serverrole=serverrole, ldap_backend=ldap_backend,
1029 ldap_backend_type=ldap_backend_type)
1031 if lp.get("server role") == "domain controller":
1032 if paths.netlogon is None:
1033 message("Existing smb.conf does not have a [netlogon] share, but you are configuring a DC.")
1034 message("Please either remove %s or see the template at %s" %
1035 ( paths.smbconf, setup_path("provision.smb.conf.dc")))
1036 assert(paths.netlogon is not None)
1038 if paths.sysvol is None:
1039 message("Existing smb.conf does not have a [sysvol] share, but you are configuring a DC.")
1040 message("Please either remove %s or see the template at %s" %
1041 (paths.smbconf, setup_path("provision.smb.conf.dc")))
1042 assert(paths.sysvol is not None)
1044 policy_path = os.path.join(paths.sysvol, names.dnsdomain, "Policies",
1045 "{" + policyguid + "}")
1046 os.makedirs(policy_path, 0755)
1047 open(os.path.join(policy_path, "GPT.INI"), 'w').write("")
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)
1087 create_named_conf(paths.namedconf, setup_path, realm=names.realm,
1088 dnsdomain=names.dnsdomain, private_dir=paths.private_dir)
1090 create_named_txt(paths.namedtxt, setup_path, realm=names.realm,
1091 dnsdomain=names.dnsdomain, private_dir=paths.private_dir,
1092 keytab_name=paths.dns_keytab)
1093 message("See %s for an example configuration include file for BIND" % paths.namedconf)
1094 message("and %s for further documentation required for secure DNS updates" % paths.namedtxt)
1096 create_krb5_conf(paths.krb5conf, setup_path, dnsdomain=names.dnsdomain,
1097 hostname=names.hostname, realm=names.realm)
1098 message("A Kerberos configuration suitable for Samba 4 has been generated at %s" % paths.krb5conf)
1100 create_phpldapadmin_config(paths.phpldapadminconfig, setup_path,
1103 message("Please install the phpLDAPadmin configuration located at %s into /etc/phpldapadmin/config.php" % paths.phpldapadminconfig)
1105 message("Once the above files are installed, your Samba4 server will be ready to use")
1106 message("Server Role: %s" % serverrole)
1107 message("Hostname: %s" % names.hostname)
1108 message("NetBIOS Domain: %s" % names.domain)
1109 message("DNS Domain: %s" % names.dnsdomain)
1110 message("DOMAIN SID: %s" % str(domainsid))
1111 message("Admin password: %s" % adminpass)
1113 result = ProvisionResult()
1114 result.domaindn = domaindn
1115 result.paths = paths
1117 result.samdb = samdb
1121 def provision_become_dc(setup_dir=None,
1122 smbconf=None, targetdir=None, realm=None,
1123 rootdn=None, domaindn=None, schemadn=None, configdn=None,
1125 domain=None, hostname=None, domainsid=None,
1126 adminpass=None, krbtgtpass=None, domainguid=None,
1127 policyguid=None, invocationid=None, machinepass=None,
1128 dnspass=None, root=None, nobody=None, nogroup=None, users=None,
1129 wheel=None, backup=None, aci=None, serverrole=None,
1130 ldap_backend=None, ldap_backend_type=None, sitename=None):
1133 """print a message if quiet is not set."""
1136 return provision(setup_dir, message, system_session(), None,
1137 smbconf=smbconf, targetdir=targetdir, samdb_fill=FILL_DRS, realm=realm,
1138 rootdn=rootdn, domaindn=domaindn, schemadn=schemadn, configdn=configdn, serverdn=serverdn,
1139 domain=domain, hostname=hostname, hostip="127.0.0.1", domainsid=domainsid, machinepass=machinepass, serverrole="domain controller", sitename=sitename)
1142 def setup_db_config(setup_path, dbdir):
1143 """Setup a Berkeley database.
1145 :param setup_path: Setup path function.
1146 :param dbdir: Database directory."""
1147 if not os.path.isdir(os.path.join(dbdir, "bdb-logs")):
1148 os.makedirs(os.path.join(dbdir, "bdb-logs"), 0700)
1149 if not os.path.isdir(os.path.join(dbdir, "tmp")):
1150 os.makedirs(os.path.join(dbdir, "tmp"), 0700)
1152 setup_file(setup_path("DB_CONFIG"), os.path.join(dbdir, "DB_CONFIG"),
1153 {"LDAPDBDIR": dbdir})
1157 def provision_backend(setup_dir=None, message=None,
1158 smbconf=None, targetdir=None, realm=None,
1159 rootdn=None, domaindn=None, schemadn=None, configdn=None,
1160 domain=None, hostname=None, adminpass=None, root=None, serverrole=None,
1161 ldap_backend_type=None, ldap_backend_port=None):
1163 def setup_path(file):
1164 return os.path.join(setup_dir, file)
1166 if hostname is None:
1167 hostname = socket.gethostname().split(".")[0].lower()
1170 root = findnss(pwd.getpwnam, ["root"])[0]
1172 if adminpass is None:
1173 adminpass = misc.random_password(12)
1175 if targetdir is not None:
1176 if (not os.path.exists(os.path.join(targetdir, "etc"))):
1177 os.makedirs(os.path.join(targetdir, "etc"))
1178 smbconf = os.path.join(targetdir, "etc", "smb.conf")
1180 # only install a new smb.conf if there isn't one there already
1181 if not os.path.exists(smbconf):
1182 make_smbconf(smbconf, setup_path, hostname, domain, realm, serverrole,
1185 lp = param.LoadParm()
1188 names = guess_names(lp=lp, hostname=hostname, domain=domain,
1189 dnsdomain=realm, serverrole=serverrole,
1190 rootdn=rootdn, domaindn=domaindn, configdn=configdn,
1193 paths = provision_paths_from_lp(lp, names.dnsdomain)
1195 if not os.path.isdir(paths.ldapdir):
1196 os.makedirs(paths.ldapdir)
1197 schemadb_path = os.path.join(paths.ldapdir, "schema-tmp.ldb")
1199 os.unlink(schemadb_path)
1203 schemadb = Ldb(schemadb_path, lp=lp)
1205 prefixmap = open(setup_path("prefixMap.txt"), 'r').read()
1207 setup_add_ldif(schemadb, setup_path("provision_schema_basedn.ldif"),
1208 {"SCHEMADN": names.schemadn,
1210 "EXTENSIBLEOBJECT": "# no objectClass: extensibleObject for local ldb"
1212 setup_modify_ldif(schemadb,
1213 setup_path("provision_schema_basedn_modify.ldif"), \
1214 {"SCHEMADN": names.schemadn,
1215 "NETBIOSNAME": names.netbiosname,
1216 "DEFAULTSITE": DEFAULTSITE,
1217 "CONFIGDN": names.configdn,
1218 "SERVERDN": names.serverdn,
1219 "PREFIXMAP_B64": b64encode(prefixmap)
1222 setup_add_ldif(schemadb, setup_path("schema_samba4.ldif"),
1223 {"SCHEMADN": names.schemadn })
1224 setup_add_ldif(schemadb, setup_path("schema.ldif"),
1225 {"SCHEMADN": names.schemadn})
1227 if ldap_backend_type == "fedora-ds":
1228 if ldap_backend_port is not None:
1229 serverport = "ServerPort=%d" % ldap_backend_port
1233 setup_file(setup_path("fedorads.inf"), paths.fedoradsinf,
1235 "HOSTNAME": hostname,
1236 "DNSDOMAIN": names.dnsdomain,
1237 "LDAPDIR": paths.ldapdir,
1238 "DOMAINDN": names.domaindn,
1239 "LDAPMANAGERDN": names.ldapmanagerdn,
1240 "LDAPMANAGERPASS": adminpass,
1241 "SERVERPORT": serverport})
1243 setup_file(setup_path("fedorads-partitions.ldif"), paths.fedoradspartitions,
1244 {"CONFIGDN": names.configdn,
1245 "SCHEMADN": names.schemadn,
1248 mapping = "schema-map-fedora-ds-1.0"
1249 backend_schema = "99_ad.ldif"
1251 slapdcommand="Initailise Fedora DS with: setup-ds.pl --file=%s" % paths.fedoradsinf
1253 elif ldap_backend_type == "openldap":
1254 attrs = ["linkID", "lDAPDisplayName"]
1255 res = schemadb.search(expression="(&(&(linkID=*)(!(linkID:1.2.840.113556.1.4.803:=1)))(objectclass=attributeSchema))", base=names.schemadn, scope=SCOPE_SUBTREE, attrs=attrs)
1257 memberof_config = "# Generated from schema in %s\n" % schemadb_path
1258 refint_attributes = ""
1259 for i in range (0, len(res)):
1260 expression = "(&(objectclass=attributeSchema)(linkID=%d))" % (int(res[i]["linkID"][0])+1)
1261 target = schemadb.searchone(basedn=names.schemadn,
1262 expression=expression,
1263 attribute="lDAPDisplayName",
1264 scope=SCOPE_SUBTREE)
1265 if target is not None:
1266 refint_attributes = refint_attributes + " " + target + " " + res[i]["lDAPDisplayName"][0]
1268 memberof_config += read_and_sub_file(setup_path("memberof.conf"),
1269 { "MEMBER_ATTR" : str(res[i]["lDAPDisplayName"][0]),
1270 "MEMBEROF_ATTR" : str(target) })
1272 refint_config = read_and_sub_file(setup_path("refint.conf"),
1273 { "LINK_ATTRS" : refint_attributes})
1275 setup_file(setup_path("slapd.conf"), paths.slapdconf,
1276 {"DNSDOMAIN": names.dnsdomain,
1277 "LDAPDIR": paths.ldapdir,
1278 "DOMAINDN": names.domaindn,
1279 "CONFIGDN": names.configdn,
1280 "SCHEMADN": names.schemadn,
1281 "MEMBEROF_CONFIG": memberof_config,
1282 "REFINT_CONFIG": refint_config})
1283 setup_file(setup_path("modules.conf"), paths.modulesconf,
1284 {"REALM": names.realm})
1286 setup_db_config(setup_path, os.path.join(paths.ldapdir, "db", "user"))
1287 setup_db_config(setup_path, os.path.join(paths.ldapdir, "db", "config"))
1288 setup_db_config(setup_path, os.path.join(paths.ldapdir, "db", "schema"))
1290 if not os.path.exists(os.path.join(paths.ldapdir, "db", "samba", "cn=samba")):
1291 os.makedirs(os.path.join(paths.ldapdir, "db", "samba", "cn=samba"))
1293 setup_file(setup_path("cn=samba.ldif"),
1294 os.path.join(paths.ldapdir, "db", "samba", "cn=samba.ldif"),
1295 { "UUID": str(uuid.uuid4()),
1296 "LDAPTIME": timestring(int(time.time()))} )
1297 setup_file(setup_path("cn=samba-admin.ldif"),
1298 os.path.join(paths.ldapdir, "db", "samba", "cn=samba", "cn=samba-admin.ldif"),
1299 {"LDAPADMINPASS_B64": b64encode(adminpass),
1300 "UUID": str(uuid.uuid4()),
1301 "LDAPTIME": timestring(int(time.time()))} )
1303 mapping = "schema-map-openldap-2.3"
1304 backend_schema = "backend-schema.schema"
1306 ldapi_uri = "ldapi://" + urllib.quote(os.path.join(paths.private_dir, "ldap", "ldapi"), safe="")
1307 if ldap_backend_port is not None:
1308 server_port_string = " -h ldap://0.0.0.0:%d" % ldap_backend_port
1310 server_port_string = ""
1311 slapdcommand="Start slapd with: slapd -f " + paths.ldapdir + "/slapd.conf -h " + ldapi_uri + server_port_string
1314 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)
1316 os.system(schema_command)
1318 message("Your %s Backend for Samba4 is now configured, and is ready to be started" % ldap_backend_type)
1319 message("Server Role: %s" % serverrole)
1320 message("Hostname: %s" % names.hostname)
1321 message("DNS Domain: %s" % names.dnsdomain)
1322 message("Base DN: %s" % names.domaindn)
1324 if ldap_backend_type == "openldap":
1325 message("LDAP admin user: samba-admin")
1327 message("LDAP admin DN: %s" % names.ldapmanagerdn)
1329 message("LDAP admin password: %s" % adminpass)
1330 message(slapdcommand)
1333 def create_phpldapadmin_config(path, setup_path, ldapi_uri):
1334 """Create a PHP LDAP admin configuration file.
1336 :param path: Path to write the configuration to.
1337 :param setup_path: Function to generate setup paths.
1339 setup_file(setup_path("phpldapadmin-config.php"), path,
1340 {"S4_LDAPI_URI": ldapi_uri})
1343 def create_zone_file(path, setup_path, dnsdomain, domaindn,
1344 hostip, hostip6, hostname, dnspass, realm, domainguid, hostguid):
1345 """Write out a DNS zone file, from the info in the current database.
1347 :param path: Path of the new zone file.
1348 :param setup_path: Setup path function.
1349 :param dnsdomain: DNS Domain name
1350 :param domaindn: DN of the Domain
1351 :param hostip: Local IPv4 IP
1352 :param hostip6: Local IPv6 IP
1353 :param hostname: Local hostname
1354 :param dnspass: Password for DNS
1355 :param realm: Realm name
1356 :param domainguid: GUID of the domain.
1357 :param hostguid: GUID of the host.
1359 assert isinstance(domainguid, str)
1361 if hostip6 is not None:
1362 hostip6_base_line = " IN AAAA " + hostip6
1363 hostip6_host_line = hostname + " IN AAAA " + hostip6
1365 hostip6_base_line = ""
1366 hostip6_host_line = ""
1368 setup_file(setup_path("provision.zone"), path, {
1369 "DNSPASS_B64": b64encode(dnspass),
1370 "HOSTNAME": hostname,
1371 "DNSDOMAIN": dnsdomain,
1374 "DOMAINGUID": domainguid,
1375 "DATESTRING": time.strftime("%Y%m%d%H"),
1376 "DEFAULTSITE": DEFAULTSITE,
1377 "HOSTGUID": hostguid,
1378 "HOSTIP6_BASE_LINE": hostip6_base_line,
1379 "HOSTIP6_HOST_LINE": hostip6_host_line,
1383 def create_named_conf(path, setup_path, realm, dnsdomain,
1385 """Write out a file containing zone statements suitable for inclusion in a
1386 named.conf file (including GSS-TSIG configuration).
1388 :param path: Path of the new named.conf file.
1389 :param setup_path: Setup path function.
1390 :param realm: Realm name
1391 :param dnsdomain: DNS Domain name
1392 :param private_dir: Path to private directory
1393 :param keytab_name: File name of DNS keytab file
1396 setup_file(setup_path("named.conf"), path, {
1397 "DNSDOMAIN": dnsdomain,
1399 "REALM_WC": "*." + ".".join(realm.split(".")[1:]),
1400 "PRIVATE_DIR": private_dir
1403 def create_named_txt(path, setup_path, realm, dnsdomain,
1404 private_dir, keytab_name):
1405 """Write out a file containing zone statements suitable for inclusion in a
1406 named.conf file (including GSS-TSIG configuration).
1408 :param path: Path of the new named.conf file.
1409 :param setup_path: Setup path function.
1410 :param realm: Realm name
1411 :param dnsdomain: DNS Domain name
1412 :param private_dir: Path to private directory
1413 :param keytab_name: File name of DNS keytab file
1416 setup_file(setup_path("named.txt"), path, {
1417 "DNSDOMAIN": dnsdomain,
1419 "DNS_KEYTAB": keytab_name,
1420 "DNS_KEYTAB_ABS": os.path.join(private_dir, keytab_name),
1421 "PRIVATE_DIR": private_dir
1424 def create_krb5_conf(path, setup_path, dnsdomain, hostname, realm):
1425 """Write out a file containing zone statements suitable for inclusion in a
1426 named.conf file (including GSS-TSIG configuration).
1428 :param path: Path of the new named.conf file.
1429 :param setup_path: Setup path function.
1430 :param dnsdomain: DNS Domain name
1431 :param hostname: Local hostname
1432 :param realm: Realm name
1435 setup_file(setup_path("krb5.conf"), path, {
1436 "DNSDOMAIN": dnsdomain,
1437 "HOSTNAME": hostname,
1442 def load_schema(setup_path, samdb, schemadn, netbiosname, configdn, sitename):
1443 """Load schema for the SamDB.
1445 :param samdb: Load a schema into a SamDB.
1446 :param setup_path: Setup path function.
1447 :param schemadn: DN of the schema
1448 :param netbiosname: NetBIOS name of the host.
1449 :param configdn: DN of the configuration
1451 schema_data = open(setup_path("schema.ldif"), 'r').read()
1452 schema_data += open(setup_path("schema_samba4.ldif"), 'r').read()
1453 schema_data = substitute_var(schema_data, {"SCHEMADN": schemadn})
1454 prefixmap = open(setup_path("prefixMap.txt"), 'r').read()
1455 prefixmap = b64encode(prefixmap)
1457 head_data = open(setup_path("provision_schema_basedn_modify.ldif"), 'r').read()
1458 head_data = substitute_var(head_data, {
1459 "SCHEMADN": schemadn,
1460 "NETBIOSNAME": netbiosname,
1461 "CONFIGDN": configdn,
1462 "DEFAULTSITE":sitename,
1463 "PREFIXMAP_B64":prefixmap
1465 samdb.attach_schema_from_ldif(head_data, schema_data)